From a5726a7a60d5d88af75f24a0e1fc7bf57c6a797e Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Mon, 1 Jun 2026 11:09:38 -0500 Subject: [PATCH] add auto save extension to LibreOffice --- main.go | 1 + post.go | 42 +++++++++++++++++++++++ post_test.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/main.go b/main.go index de79f49..94e7ea3 100644 --- a/main.go +++ b/main.go @@ -153,6 +153,7 @@ func runMain(args []string) { if isMacOS && !*noVM { setupFirecrackerVM() } + ensureLibreOfficeAutoSave() } if pyenvWG != nil { diff --git a/post.go b/post.go index 41996c1..c9593e3 100644 --- a/post.go +++ b/post.go @@ -544,3 +544,45 @@ func installGHExtension(repo string) { } } +// ── LibreOffice AutoSave Extension ────────────────────────────────────── + +func ensureLibreOfficeAutoSave() { + var unopkgPath string + if isMacOS { + unopkgPath = "/Applications/LibreOffice.app/Contents/MacOS/unopkg" + if _, err := osStat(unopkgPath); err != nil { + return + } + } else { + if !hasCmd("unopkg") { + return + } + unopkgPath = "unopkg" + } + + fmt.Println("\n[LibreOffice] LibreOffice detected. Installing AutoSave extension ...") + + tmp, err := os.MkdirTemp("", "libreoffice-autosave-") + if err != nil { + errLog(fmt.Sprintf("LibreOffice AutoSave temp dir failed: %v", err)) + return + } + defer osRemoveAll(tmp) + + url := "https://github.com/JMR-dev/LibreOfficeAutoSave/releases/latest/download/AutoSave.oxt" + dest := filepath.Join(tmp, "AutoSave.oxt") + + if !download(url, dest) { + errLog("Failed to download LibreOffice AutoSave extension") + return + } + + if !runCmd([]string{unopkgPath, "add", "-f", dest}, CmdOpts{}).OK() { + errLog("Failed to install LibreOffice AutoSave extension") + return + } + + fmt.Println(" LibreOffice AutoSave extension installed successfully.") +} + + diff --git a/post_test.go b/post_test.go index e5279dc..b30263c 100644 --- a/post_test.go +++ b/post_test.go @@ -905,4 +905,98 @@ func TestEnsurePythonLatestBackgroundInstall(t *testing.T) { } } +func TestEnsureLibreOfficeAutoSave(t *testing.T) { + defer resetMocks() + + // 1. isMacOS = false, LibreOffice not installed + isMacOS = false + hasCmd = func(name string) bool { + if name == "unopkg" { + return false + } + return true + } + var calledDownload bool + download = func(url, dest string) bool { + calledDownload = true + return true + } + ensureLibreOfficeAutoSave() + if calledDownload { + t.Error("expected download not to be called when unopkg is missing") + } + + // 2. isMacOS = true, LibreOffice not installed + isMacOS = true + osStat = func(name string) (os.FileInfo, error) { + return nil, os.ErrNotExist + } + calledDownload = false + ensureLibreOfficeAutoSave() + if calledDownload { + t.Error("expected download not to be called when unopkg is missing on macOS") + } + + // 3. isMacOS = false, LibreOffice installed, download fails + isMacOS = false + hasCmd = func(name string) bool { + return name == "unopkg" + } + download = func(url, dest string) bool { + return false + } + var runCmdCalled bool + runCmd = func(argv []string, opts CmdOpts) CmdResult { + runCmdCalled = true + return CmdResult{ExitCode: 0} + } + ensureLibreOfficeAutoSave() + if runCmdCalled { + t.Error("expected runCmd not to be called when download fails") + } + + // 4. isMacOS = false, LibreOffice installed, download succeeds, runCmd fails + download = func(url, dest string) bool { + return true + } + var unopkgArgv []string + runCmd = func(argv []string, opts CmdOpts) CmdResult { + unopkgArgv = argv + return CmdResult{ExitCode: 1} + } + ensureLibreOfficeAutoSave() + if len(unopkgArgv) == 0 || unopkgArgv[0] != "unopkg" { + t.Errorf("expected runCmd with unopkg, got: %v", unopkgArgv) + } + + // 5. isMacOS = false, LibreOffice installed, download succeeds, runCmd succeeds + runCmd = func(argv []string, opts CmdOpts) CmdResult { + unopkgArgv = argv + return CmdResult{ExitCode: 0} + } + ensureLibreOfficeAutoSave() + if len(unopkgArgv) == 0 || unopkgArgv[0] != "unopkg" || unopkgArgv[1] != "add" || unopkgArgv[2] != "-f" { + t.Errorf("expected runCmd with unopkg add -f, got: %v", unopkgArgv) + } + + // 6. isMacOS = true, LibreOffice installed, download succeeds, runCmd succeeds + isMacOS = true + osStat = func(name string) (os.FileInfo, error) { + if name == "/Applications/LibreOffice.app/Contents/MacOS/unopkg" { + return nil, nil + } + return nil, os.ErrNotExist + } + runCmd = func(argv []string, opts CmdOpts) CmdResult { + unopkgArgv = argv + return CmdResult{ExitCode: 0} + } + ensureLibreOfficeAutoSave() + expectedMacPath := "/Applications/LibreOffice.app/Contents/MacOS/unopkg" + if len(unopkgArgv) == 0 || unopkgArgv[0] != expectedMacPath { + t.Errorf("expected runCmd with %s, got: %v", expectedMacPath, unopkgArgv) + } +} + +