gitee.com/h79/goutils@v1.22.10/common/archive/e7z/7z.go (about)

     1  package e7z
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	fileconfig "gitee.com/h79/goutils/common/file/config"
     7  	"io"
     8  	"os"
     9  	"os/exec"
    10  	"runtime"
    11  )
    12  
    13  // Archive as 7z.
    14  type Archive struct {
    15  	Path     string
    16  	Filename string
    17  }
    18  
    19  // New tar archive.
    20  func New(target io.WriteCloser, path, filename string) Archive {
    21  	if target != nil {
    22  		target.Close()
    23  		os.Remove(filename)
    24  	}
    25  	return Archive{Path: path, Filename: filename}
    26  }
    27  
    28  // Close all closeables.
    29  func (a Archive) Close() error {
    30  	return nil
    31  }
    32  
    33  // Add file to the archive.
    34  func (a Archive) Add(f fileconfig.File, stream ...fileconfig.ReaderStream) error {
    35  	err := a.cmd(f)
    36  	if err != nil {
    37  		return err
    38  	}
    39  	return a.Stream(f, stream...)
    40  }
    41  
    42  func (a Archive) cmd(f fileconfig.File) error {
    43  	cmd := "7z"
    44  	switch runtime.GOOS {
    45  	case "windows":
    46  		cmd = "7z.exe"
    47  	}
    48  	return run(context.Background(), []string{cmd, "a", "-r", a.Filename, f.Source}, nil, "")
    49  }
    50  
    51  func (a Archive) Stream(f fileconfig.File, stream ...fileconfig.ReaderStream) error {
    52  	if len(stream) == 0 {
    53  		return nil
    54  	}
    55  	if f.Dir {
    56  		return nil
    57  	}
    58  	file, err := os.Open(f.Source) // #nosec
    59  	if err != nil {
    60  		return fmt.Errorf("%s: %w", f.Source, err)
    61  	}
    62  	defer func(file *os.File) {
    63  		err = file.Close()
    64  		if err != nil {
    65  		}
    66  	}(file)
    67  	for i := range stream {
    68  		stream[i].OnReader(file)
    69  	}
    70  	return nil
    71  }
    72  
    73  func run(ctx context.Context, command, env []string, dir string) error {
    74  	cmd := exec.CommandContext(ctx, command[0], command[1:]...)
    75  	cmd.Env = env
    76  	cmd.Dir = dir
    77  	out, err := cmd.CombinedOutput()
    78  	if err != nil {
    79  		return fmt.Errorf("%w: %s", err, string(out))
    80  	}
    81  	return nil
    82  }