mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
channel: master
version: 1.2.0
source-ref: D:\code\open_source\ant-chrome master
source-commit: f3d7ec5
merged-public-base: 3d264eb
141 lines
3.5 KiB
Go
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)
|
|
}
|