Files
Ant-Browser/backend/internal/automation/script_package_zip_write.go
T
ant-black 70132417ad publish: 1.2.0 snapshot (f3d7ec5)
channel: master

version: 1.2.0

source-ref: D:\code\open_source\ant-chrome master

source-commit: f3d7ec5

merged-public-base: 3d264eb
2026-05-05 18:08:10 +08:00

141 lines
3.5 KiB
Go

package automation
import (
"archive/zip"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)
const (
scriptPackageManifestName = "automation.script.json"
maxImportedZipFiles = maxImportedBundleFiles + 8
maxImportedZipBytes = maxImportedBundleBytes + (256 << 10)
)
func WriteScriptPackageZip(zipPath string, bundle ImportedBundle) error {
normalizedPath := strings.TrimSpace(zipPath)
if normalizedPath == "" {
return fmt.Errorf("script zip path is required")
}
record, files, err := collectScriptPackageExportFiles(bundle)
if err != nil {
return err
}
manifestData, err := MarshalScriptPackageManifest(record)
if err != nil {
return fmt.Errorf("marshal script package manifest failed: %w", err)
}
if err := os.MkdirAll(filepath.Dir(normalizedPath), 0o755); err != nil {
return fmt.Errorf("create script zip dir failed: %w", err)
}
tmpPath := normalizedPath + ".tmp"
_ = os.Remove(tmpPath)
file, err := os.Create(tmpPath)
if err != nil {
return fmt.Errorf("create script zip failed: %w", err)
}
success := false
defer func() {
_ = file.Close()
if !success {
_ = os.Remove(tmpPath)
}
}()
writer := zip.NewWriter(file)
if err := writeScriptZipEntry(writer, scriptPackageManifestName, manifestData); err != nil {
_ = writer.Close()
return fmt.Errorf("write script package manifest failed: %w", err)
}
for _, bundleFile := range files {
if err := writeScriptZipEntry(writer, bundleFile.Path, bundleFile.Content); err != nil {
_ = writer.Close()
return fmt.Errorf("write script package file %s failed: %w", bundleFile.Path, err)
}
}
if err := writer.Close(); err != nil {
return fmt.Errorf("finalize script zip failed: %w", err)
}
if err := file.Close(); err != nil {
return fmt.Errorf("close script zip failed: %w", err)
}
if err := replaceFile(tmpPath, normalizedPath); err != nil {
return fmt.Errorf("move script zip failed: %w", err)
}
success = true
return nil
}
func collectScriptPackageExportFiles(bundle ImportedBundle) (ScriptRecord, []ImportedBundleFile, error) {
record, err := normalizeScriptRecord(bundle.Record, ScriptRecord{})
if err != nil {
return ScriptRecord{}, nil, err
}
if err := validateImportedBundle(record, bundle.Files); err != nil {
return ScriptRecord{}, nil, err
}
fileIndex, err := buildImportedBundleFileIndex(record, bundle.Files)
if err != nil {
return ScriptRecord{}, nil, err
}
paths := make([]string, 0, len(fileIndex))
for relativePath := range fileIndex {
if isImportManifestPath(relativePath) {
continue
}
paths = append(paths, relativePath)
}
sort.Strings(paths)
files := make([]ImportedBundleFile, 0, len(paths))
for _, relativePath := range paths {
files = append(files, ImportedBundleFile{
Path: relativePath,
Content: fileIndex[relativePath],
})
}
return record, files, nil
}
func writeScriptZipEntry(writer *zip.Writer, archivePath string, content []byte) error {
normalizedPath, err := normalizeBundleFilePath(archivePath)
if err != nil {
return err
}
header := &zip.FileHeader{
Name: normalizedPath,
Method: zip.Deflate,
}
header.SetMode(0o644)
entryWriter, err := writer.CreateHeader(header)
if err != nil {
return err
}
_, err = entryWriter.Write(content)
return err
}
func replaceFile(sourcePath string, targetPath string) error {
if err := os.Rename(sourcePath, targetPath); err == nil {
return nil
}
if removeErr := os.Remove(targetPath); removeErr != nil && !os.IsNotExist(removeErr) {
return removeErr
}
return os.Rename(sourcePath, targetPath)
}