diff --git a/.gitignore b/.gitignore index 73d2738..f392381 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -dist/scripts/uosc/bin +src/uosc/bin release *.zip diff --git a/README.md b/README.md index 464b699..e8f23b8 100644 --- a/README.md +++ b/README.md @@ -708,6 +708,16 @@ Using `'user'` as `script_id` will overwrite user's `disable_elements` config. E ## Contributing +### Setup + +If you want to test or work on something that involves ziggy (our multitool binary, currently handles searching & downloading subtitles), you first need to build it with: + +``` +tools/build ziggy +``` + +This requires [`go`](https://go.dev/dl/) to be installed and in path. If you don't want to bother with installing go, and there were no changes to ziggy, you can just use the binaries from [latest release](https://github.com/tomasklaen/uosc/releases/latest/download/uosc.zip). Place folder `scripts/uosc/bin` from `uosc.zip` into `src/uosc/bin`. + ### Localization If you want to help localizing uosc by either adding a new locale or fixing one that is not up to date, start by running this while in the repository root: @@ -716,11 +726,11 @@ If you want to help localizing uosc by either adding a new locale or fixing one tools/intl languagecode ``` -`languagecode` can be any existing locale in `dist/scripts/uosc/intl/` directory, or any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). If it doesn't exist yet, the `intl` tool will create it. +`languagecode` can be any existing locale in `src/uosc/intl/` directory, or any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). If it doesn't exist yet, the `intl` tool will create it. This will parse the codebase for localization strings and use them to either update existing locale by removing unused and setting untranslated strings to `null`, or create a new one with all `null` strings. -You can then navigate to `dist/scripts/uosc/intl/languagecode.json` and start translating. +You can then navigate to `src/uosc/intl/languagecode.json` and start translating. ## Why _uosc_? diff --git a/dist/fonts/uosc_icons.otf b/src/fonts/uosc_icons.otf similarity index 100% rename from dist/fonts/uosc_icons.otf rename to src/fonts/uosc_icons.otf diff --git a/dist/fonts/uosc_textures.ttf b/src/fonts/uosc_textures.ttf similarity index 100% rename from dist/fonts/uosc_textures.ttf rename to src/fonts/uosc_textures.ttf diff --git a/src/tools/lib/zip.go b/src/tools/lib/zip.go new file mode 100644 index 0000000..4b80b90 --- /dev/null +++ b/src/tools/lib/zip.go @@ -0,0 +1,141 @@ +package lib + +import ( + "archive/zip" + "io" + "io/fs" + "os" + "path/filepath" +) + +/* +`files` format: + +``` + + map[string]string{ + "/path/on/disk/file1.txt": "file1.txt", + "/path/on/disk/file2.txt": "subfolder/file2.txt", + "/path/on/disk/file3.txt": "", // put in root of archive as file3.txt + "/path/on/disk/file4.txt": "subfolder/", // put in subfolder as file4.txt + "/path/on/disk/folder": "Custom Folder", // contents added recursively + } + +``` +*/ +func ZipFilesWithHeaders(files map[string]string, outputFile string, headerMod HeaderModFn) (ZipStats, error) { + path, err := filepath.Abs(outputFile) + if err != nil { + return ZipStats{}, err + } + dirname := filepath.Dir(path) + err = os.MkdirAll(dirname, os.ModePerm) + if err != nil { + return ZipStats{}, err + } + + f, err := os.Create(path) + if err != nil { + return ZipStats{}, err + } + defer f.Close() + zw := zip.NewWriter(f) + defer zw.Close() + + var filesNum, bytes int64 + + addFile := func(srcPath string, nameInArchive string, entry fs.DirEntry) error { + src, err := os.Open(srcPath) + if err != nil { + return err + } + defer src.Close() + + info, err := entry.Info() + if err != nil { + return err + } + + header, err := zip.FileInfoHeader(info) + if err != nil { + return err + } + header.Name = nameInArchive + header.Method = zip.Deflate + header = headerMod(header) + if header.Name == "" { + return nil + } + + dst, err := zw.CreateHeader(header) + if err != nil { + return err + } + + written, err := io.Copy(dst, src) + if err != nil { + return err + } + + bytes += written + filesNum++ + return nil + } + + for src, dst := range files { + stat, err := os.Stat(src) + if err != nil { + return ZipStats{}, err + } + + basename := filepath.Base(src) + if dst == "" { + dst = basename + } else if dst[len(dst)-1:] == "/" { + dst = dst + basename + } + + if !stat.IsDir() { + addFile(src, dst, fs.FileInfoToDirEntry(stat)) + continue + } + + err = filepath.WalkDir(src, func(path string, entry fs.DirEntry, err error) error { + if err != nil { + return err + } + if entry.IsDir() { + return nil + } + + relativePath, err := filepath.Rel(src, path) + if err != nil { + return err + } + + err = addFile(path, dst+"/"+filepath.ToSlash(relativePath), entry) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + return ZipStats{}, err + } + } + + return ZipStats{ + FilesNum: filesNum, + Bytes: bytes, + }, nil +} + +// If `HeaderModFn` function sets `header.Name` to empty string, file will be skipped. +type HeaderModFn func(header *zip.FileHeader) *zip.FileHeader + +type ZipStats struct { + FilesNum int64 + Bytes int64 +} diff --git a/src/tools/tools.go b/src/tools/tools.go new file mode 100644 index 0000000..20a1d0f --- /dev/null +++ b/src/tools/tools.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "os" + "uosc/bins/src/tools/tools" +) + +func main() { + command := "help" + + if len(os.Args) > 1 { + command = os.Args[1] + } + + switch command { + case "intl": + tools.Intl(os.Args[2:]) + + case "package": + tools.Packager(os.Args[2:]) + + // Help + default: + fmt.Printf(`uosc tools. + +Usage: + + tools [args] + +Available s: + + intl - localization helper + package - package uosc release files + +Run 'tools -h/--help' for help on how to use each tool. +`) + } +} diff --git a/src/tools/tools/base.go b/src/tools/tools/base.go new file mode 100644 index 0000000..d925be6 --- /dev/null +++ b/src/tools/tools/base.go @@ -0,0 +1,12 @@ +package tools + +func check(err error) { + if err != nil { + panic(err) + } +} + +func must[T any](t T, err error) T { + check(err) + return t +} diff --git a/src/intl/intl.go b/src/tools/tools/intl.go similarity index 94% rename from src/intl/intl.go rename to src/tools/tools/intl.go index 2da9da6..861652c 100644 --- a/src/intl/intl.go +++ b/src/tools/tools/intl.go @@ -1,4 +1,4 @@ -package main +package tools import ( "bufio" @@ -15,10 +15,10 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -func main() { +func Intl(args []string) { cwd, err := os.Getwd() check(err) - uoscRootRelative := "dist/scripts/uosc" + uoscRootRelative := "src/uosc" intlRootRelative := uoscRootRelative + "/intl" uoscRoot := filepath.Join(cwd, uoscRootRelative) @@ -29,7 +29,7 @@ func main() { } // Help - if len(os.Args) <= 1 || len(os.Args) > 1 && sets.New("--help", "-h").Has(os.Args[1]) { + if len(args) < 1 || len(args) > 0 && sets.New("--help", "-h").Has(args[0]) { fmt.Printf(`Updates or creates a localization files by parsing the codebase for localization strings, and (re)constructing the locale files with them. Strings no longer in use are removed. Strings not yet translated are set to "null". @@ -58,15 +58,14 @@ Examples: } var locales []string - if os.Args[1] == "all" { + if args[0] == "all" { intlRoot := filepath.Join(cwd, intlRootRelative) locales = must(listFilenamesOfType(intlRoot, ".json")) } else { - locales = strings.Split(os.Args[1], ",") + locales = strings.Split(args[0], ",") } holePunchLocales(locales, uoscRoot) - } func holePunchLocales(locales []string, rootPath string) { @@ -237,17 +236,6 @@ func holePunchLocales(locales []string, rootPath string) { } } -func check(err error) { - if err != nil { - panic(err) - } -} - -func must[T any](t T, err error) T { - check(err) - return t -} - func listFilenamesOfType(directoryPath string, extension string) ([]string, error) { files := []string{} extension = strings.ToLower(extension) diff --git a/src/tools/tools/packager.go b/src/tools/tools/packager.go new file mode 100644 index 0000000..41863b2 --- /dev/null +++ b/src/tools/tools/packager.go @@ -0,0 +1,65 @@ +package tools + +import ( + "archive/zip" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "uosc/bins/src/tools/lib" + + "k8s.io/apimachinery/pkg/util/sets" +) + +func Packager(args []string) { + // Display help. + if len(args) > 0 && sets.New("--help", "-h").Has(args[0]) { + fmt.Printf(`Packages uosc release files into 'release/' directory, while ensuring binaries inside the zip file are marked as executable even when packaged on windows (otherwise this could've just be a simple .ps1/.sh file).`) + os.Exit(0) + } + + cwd := must(os.Getwd()) + releaseRoot := filepath.Join(cwd, "release") + releaseArchiveSrcDstMap := map[string]string{ + filepath.Join(cwd, "src/fonts"): "", + filepath.Join(cwd, "src/uosc"): "scripts/", + } + releaseConfigPath := filepath.Join(releaseRoot, "uosc.conf") + releaseArchivePath := filepath.Join(releaseRoot, "uosc.zip") + sourceConfigPath := filepath.Join(cwd, "src/uosc.conf") + + // Naive check binaries are built. + bins := must(os.ReadDir(filepath.Join(cwd, "src/uosc/bin"))) + if len(bins) == 0 { + check(errors.New("binaries are not built ('src/uosc/bin' is empty)")) + } + + // Cleanup old release. + check(os.RemoveAll(releaseRoot)) + + // Package new release + var modHeaders lib.HeaderModFn = func(header *zip.FileHeader) *zip.FileHeader { + // Mark binaries as executable. + if strings.HasPrefix(header.Name, "scripts/uosc/bin/") { + header.SetMode(0755) + } + return header + } + stats := must(lib.ZipFilesWithHeaders(releaseArchiveSrcDstMap, releaseArchivePath, modHeaders)) + + // Copy config to release folder for convenience. + configFileSrc := must(os.Open(sourceConfigPath)) + configFileDst := must(os.Create(releaseConfigPath)) + confSize := must(io.Copy(configFileDst, configFileSrc)) + + fmt.Printf( + "Packaging into: %s\n- uosc.zip: %.2f MB, %d files\n- uosc.conf: %.1f KB", + filepath.ToSlash(must(filepath.Rel(cwd, releaseRoot)))+"/", + float64(stats.Bytes)/1024/1024, + stats.FilesNum, + float64(confSize)/1024, + ) +} diff --git a/dist/script-opts/uosc.conf b/src/uosc.conf similarity index 100% rename from dist/script-opts/uosc.conf rename to src/uosc.conf diff --git a/dist/scripts/uosc/elements/BufferingIndicator.lua b/src/uosc/elements/BufferingIndicator.lua similarity index 100% rename from dist/scripts/uosc/elements/BufferingIndicator.lua rename to src/uosc/elements/BufferingIndicator.lua diff --git a/dist/scripts/uosc/elements/Button.lua b/src/uosc/elements/Button.lua similarity index 100% rename from dist/scripts/uosc/elements/Button.lua rename to src/uosc/elements/Button.lua diff --git a/dist/scripts/uosc/elements/Controls.lua b/src/uosc/elements/Controls.lua similarity index 100% rename from dist/scripts/uosc/elements/Controls.lua rename to src/uosc/elements/Controls.lua diff --git a/dist/scripts/uosc/elements/Curtain.lua b/src/uosc/elements/Curtain.lua similarity index 100% rename from dist/scripts/uosc/elements/Curtain.lua rename to src/uosc/elements/Curtain.lua diff --git a/dist/scripts/uosc/elements/CycleButton.lua b/src/uosc/elements/CycleButton.lua similarity index 100% rename from dist/scripts/uosc/elements/CycleButton.lua rename to src/uosc/elements/CycleButton.lua diff --git a/dist/scripts/uosc/elements/Element.lua b/src/uosc/elements/Element.lua similarity index 100% rename from dist/scripts/uosc/elements/Element.lua rename to src/uosc/elements/Element.lua diff --git a/dist/scripts/uosc/elements/Elements.lua b/src/uosc/elements/Elements.lua similarity index 100% rename from dist/scripts/uosc/elements/Elements.lua rename to src/uosc/elements/Elements.lua diff --git a/dist/scripts/uosc/elements/Menu.lua b/src/uosc/elements/Menu.lua similarity index 100% rename from dist/scripts/uosc/elements/Menu.lua rename to src/uosc/elements/Menu.lua diff --git a/dist/scripts/uosc/elements/PauseIndicator.lua b/src/uosc/elements/PauseIndicator.lua similarity index 100% rename from dist/scripts/uosc/elements/PauseIndicator.lua rename to src/uosc/elements/PauseIndicator.lua diff --git a/dist/scripts/uosc/elements/Speed.lua b/src/uosc/elements/Speed.lua similarity index 100% rename from dist/scripts/uosc/elements/Speed.lua rename to src/uosc/elements/Speed.lua diff --git a/dist/scripts/uosc/elements/Timeline.lua b/src/uosc/elements/Timeline.lua similarity index 100% rename from dist/scripts/uosc/elements/Timeline.lua rename to src/uosc/elements/Timeline.lua diff --git a/dist/scripts/uosc/elements/TopBar.lua b/src/uosc/elements/TopBar.lua similarity index 100% rename from dist/scripts/uosc/elements/TopBar.lua rename to src/uosc/elements/TopBar.lua diff --git a/dist/scripts/uosc/elements/Updater.lua b/src/uosc/elements/Updater.lua similarity index 100% rename from dist/scripts/uosc/elements/Updater.lua rename to src/uosc/elements/Updater.lua diff --git a/dist/scripts/uosc/elements/Volume.lua b/src/uosc/elements/Volume.lua similarity index 100% rename from dist/scripts/uosc/elements/Volume.lua rename to src/uosc/elements/Volume.lua diff --git a/dist/scripts/uosc/elements/WindowBorder.lua b/src/uosc/elements/WindowBorder.lua similarity index 100% rename from dist/scripts/uosc/elements/WindowBorder.lua rename to src/uosc/elements/WindowBorder.lua diff --git a/dist/scripts/uosc/intl/de.json b/src/uosc/intl/de.json similarity index 100% rename from dist/scripts/uosc/intl/de.json rename to src/uosc/intl/de.json diff --git a/dist/scripts/uosc/intl/es.json b/src/uosc/intl/es.json similarity index 100% rename from dist/scripts/uosc/intl/es.json rename to src/uosc/intl/es.json diff --git a/dist/scripts/uosc/intl/fr.json b/src/uosc/intl/fr.json similarity index 100% rename from dist/scripts/uosc/intl/fr.json rename to src/uosc/intl/fr.json diff --git a/dist/scripts/uosc/intl/ro.json b/src/uosc/intl/ro.json similarity index 100% rename from dist/scripts/uosc/intl/ro.json rename to src/uosc/intl/ro.json diff --git a/dist/scripts/uosc/intl/ru.json b/src/uosc/intl/ru.json similarity index 100% rename from dist/scripts/uosc/intl/ru.json rename to src/uosc/intl/ru.json diff --git a/dist/scripts/uosc/intl/uk.json b/src/uosc/intl/uk.json similarity index 100% rename from dist/scripts/uosc/intl/uk.json rename to src/uosc/intl/uk.json diff --git a/dist/scripts/uosc/intl/zh-hans.json b/src/uosc/intl/zh-hans.json similarity index 100% rename from dist/scripts/uosc/intl/zh-hans.json rename to src/uosc/intl/zh-hans.json diff --git a/dist/scripts/uosc/lib/ass.lua b/src/uosc/lib/ass.lua similarity index 100% rename from dist/scripts/uosc/lib/ass.lua rename to src/uosc/lib/ass.lua diff --git a/dist/scripts/uosc/lib/cursor.lua b/src/uosc/lib/cursor.lua similarity index 100% rename from dist/scripts/uosc/lib/cursor.lua rename to src/uosc/lib/cursor.lua diff --git a/dist/scripts/uosc/lib/intl.lua b/src/uosc/lib/intl.lua similarity index 100% rename from dist/scripts/uosc/lib/intl.lua rename to src/uosc/lib/intl.lua diff --git a/dist/scripts/uosc/lib/menus.lua b/src/uosc/lib/menus.lua similarity index 100% rename from dist/scripts/uosc/lib/menus.lua rename to src/uosc/lib/menus.lua diff --git a/dist/scripts/uosc/lib/std.lua b/src/uosc/lib/std.lua similarity index 100% rename from dist/scripts/uosc/lib/std.lua rename to src/uosc/lib/std.lua diff --git a/dist/scripts/uosc/lib/text.lua b/src/uosc/lib/text.lua similarity index 100% rename from dist/scripts/uosc/lib/text.lua rename to src/uosc/lib/text.lua diff --git a/dist/scripts/uosc/lib/utils.lua b/src/uosc/lib/utils.lua similarity index 100% rename from dist/scripts/uosc/lib/utils.lua rename to src/uosc/lib/utils.lua diff --git a/dist/scripts/uosc/main.lua b/src/uosc/main.lua similarity index 100% rename from dist/scripts/uosc/main.lua rename to src/uosc/main.lua diff --git a/tools/build b/tools/build index c297cd9..68e438c 100755 --- a/tools/build +++ b/tools/build @@ -2,7 +2,7 @@ # Script to build one of uosc binaries. # Requirements: go, upx (if compressing) # Usage: tools/build [-c] -# can be: intl, ziggy +# can be: tools, ziggy # -c enables binary compression with upx (only needed for builds being released) abort() { @@ -14,28 +14,28 @@ if [ ! -d "$PWD/src" ]; then abort "'src' directory not found. Make sure this script is run in uosc's repository root as current working directory." fi -if [ "$1" = "intl" ]; then +if [ "$1" = "tools" ]; then export GOARCH="amd64" - src="./src/intl/intl.go" + src="./src/tools/tools.go" out_dir="./tools" echo "Building for Windows..." export GOOS="windows" - go build -ldflags "-s -w" -o "$out_dir/intl.exe" $src + go build -ldflags "-s -w" -o "$out_dir/tools.exe" $src echo "Building for Linux..." export GOOS="linux" - go build -ldflags "-s -w" -o "$out_dir/intl-linux" $src + go build -ldflags "-s -w" -o "$out_dir/tools-linux" $src echo "Building for MacOS..." export GOOS="darwin" - go build -ldflags "-s -w" -o "$out_dir/intl-darwin" $src + go build -ldflags "-s -w" -o "$out_dir/tools-darwin" $src if [ "$2" = "-c" ]; then echo "Compressing binaries..." - upx --brute "$out_dir/intl.exe" - upx --brute "$out_dir/intl-linux" - upx --brute "$out_dir/intl-darwin" + upx --brute "$out_dir/tools.exe" + upx --brute "$out_dir/tools-linux" + upx --brute "$out_dir/tools-darwin" fi unset GOARCH @@ -76,6 +76,6 @@ else echo "Tool to build one of uosc binaries. Requires go to be installed and in path." echo "Requirements: go, upx (if compressing)" echo "Usage: tools/build [-c]" - echo " can be: intl, ziggy" + echo " can be: tools, ziggy" echo "-c enables binary compression (requires upx)" fi diff --git a/tools/build.ps1 b/tools/build.ps1 index 07f0545..e20c096 100644 --- a/tools/build.ps1 +++ b/tools/build.ps1 @@ -14,28 +14,28 @@ if (!(Test-Path -Path "$PWD/src" -PathType Container)) { Abort("'src' directory not found. Make sure this script is run in uosc's repository root as current working directory.") } -if ($args[0] -eq "intl") { +if ($args[0] -eq "tools") { $env:GOARCH = "amd64" - $Src = "./src/intl/intl.go" + $Src = "./src/tools/tools.go" $OutDir = "./tools" Write-Output "Building for Windows..." $env:GOOS = "windows" - go build -ldflags "-s -w" -o "$OutDir/intl.exe" $Src + go build -ldflags "-s -w" -o "$OutDir/tools.exe" $Src Write-Output "Building for Linux..." $env:GOOS = "linux" - go build -ldflags "-s -w" -o "$OutDir/intl-linux" $Src + go build -ldflags "-s -w" -o "$OutDir/tools-linux" $Src Write-Output "Building for MacOS..." $env:GOOS = "darwin" - go build -ldflags "-s -w" -o "$OutDir/intl-darwin" $Src + go build -ldflags "-s -w" -o "$OutDir/tools-darwin" $Src if ($args[1] -eq "-c") { Write-Output "Compressing binaries..." - upx --brute "$OutDir/intl.exe" - upx --brute "$OutDir/intl-linux" - upx --brute "$OutDir/intl-darwin" + upx --brute "$OutDir/tools.exe" + upx --brute "$OutDir/tools-linux" + upx --brute "$OutDir/tools-darwin" } Remove-Item Env:\GOOS @@ -44,7 +44,7 @@ if ($args[0] -eq "intl") { elseif ($args[0] -eq "ziggy") { $env:GOARCH = "amd64" $Src = "./src/ziggy/ziggy.go" - $OutDir = "./dist/scripts/uosc/bin" + $OutDir = "./src/uosc/bin" if (!(Test-Path $OutDir)) { New-Item -ItemType Directory -Force -Path $OutDir > $null diff --git a/tools/intl b/tools/intl index a7dec0d..69ac7ea 100755 --- a/tools/intl +++ b/tools/intl @@ -1,7 +1,7 @@ #!/usr/bin/env bash SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) if [ "$(uname)" == "Darwin" ]; then - "$SCRIPT_DIR/intl-darwin" $* + "$SCRIPT_DIR/tools-darwin" intl $* else - "$SCRIPT_DIR/intl-linux" $* + "$SCRIPT_DIR/tools-linux" intl $* fi diff --git a/tools/intl-darwin b/tools/intl-darwin deleted file mode 100755 index dd96b51..0000000 Binary files a/tools/intl-darwin and /dev/null differ diff --git a/tools/intl-linux b/tools/intl-linux deleted file mode 100755 index 5cda821..0000000 Binary files a/tools/intl-linux and /dev/null differ diff --git a/tools/intl.exe b/tools/intl.exe deleted file mode 100644 index 48ce34b..0000000 Binary files a/tools/intl.exe and /dev/null differ diff --git a/tools/intl.ps1 b/tools/intl.ps1 new file mode 100644 index 0000000..6bad20c --- /dev/null +++ b/tools/intl.ps1 @@ -0,0 +1 @@ +& "$PSScriptRoot/tools.exe" intl $args diff --git a/tools/package b/tools/package new file mode 100755 index 0000000..5c990c4 --- /dev/null +++ b/tools/package @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +if [ "$(uname)" == "Darwin" ]; then + "$SCRIPT_DIR/tools-darwin" package $* +else + "$SCRIPT_DIR/tools-linux" package $* +fi diff --git a/tools/package.ps1 b/tools/package.ps1 index 6bed30b..3968341 100644 --- a/tools/package.ps1 +++ b/tools/package.ps1 @@ -1,43 +1 @@ -# Package uosc release. - -Function Abort($Message) { - Write-Output "Error: $Message" - Write-Output "Aborting!" - Exit 1 -} - -Function DeleteIfExists($Path) { - if (Test-Path $Path) { - Remove-Item -LiteralPath $Path -Force -Recurse > $null - } -} - -if (!(Test-Path -Path "$PWD/src" -PathType Container)) { - Abort("'src' directory not found. Make sure this script is run in uosc's repository root as current working directory.") -} - -if (!(Test-Path -Path "$PWD/dist/scripts/uosc/bin/ziggy-linux" -PathType Leaf)) { - Abort("'dist/scripts/uosc/bin' binaries are not build.") -} - -$ReleaseDir = "release" - -# Clear old -DeleteIfExists($ReleaseDir) -if (!(Test-Path $ReleaseDir)) { - try { - New-Item -ItemType Directory -Force -Path $ReleaseDir > $null - } - catch { - Abort("Couldn't create release directory.") - } -} - -# Package new -$compress = @{ - LiteralPath = "dist/fonts", "dist/scripts" - CompressionLevel = "Optimal" - DestinationPath = "$ReleaseDir/uosc.zip" -} -Compress-Archive @compress -Copy-Item "dist/script-opts/uosc.conf" -Destination $ReleaseDir +& "$PSScriptRoot/tools.exe" package $args diff --git a/tools/tools-darwin b/tools/tools-darwin new file mode 100755 index 0000000..a74f02b Binary files /dev/null and b/tools/tools-darwin differ diff --git a/tools/tools-linux b/tools/tools-linux new file mode 100755 index 0000000..c59f7f8 Binary files /dev/null and b/tools/tools-linux differ diff --git a/tools/tools.exe b/tools/tools.exe new file mode 100644 index 0000000..de86c0f Binary files /dev/null and b/tools/tools.exe differ