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

     1  package archive
     2  
     3  import (
     4  	"fmt"
     5  	"gitee.com/h79/goutils/common/archive/e7z"
     6  	"gitee.com/h79/goutils/common/archive/gzip"
     7  	"gitee.com/h79/goutils/common/archive/tar"
     8  	"gitee.com/h79/goutils/common/archive/targz"
     9  	"gitee.com/h79/goutils/common/archive/tarxz"
    10  	"gitee.com/h79/goutils/common/archive/zip"
    11  	fileconfig "gitee.com/h79/goutils/common/file/config"
    12  	"io"
    13  	"os"
    14  )
    15  
    16  type Config struct {
    17  	Path   string
    18  	File   string
    19  	Format string
    20  }
    21  
    22  // Archive represents a compression archive files from disk can be written to.
    23  type Archive interface {
    24  	Close() error
    25  	Add(f fileconfig.File, stream ...fileconfig.ReaderStream) error
    26  }
    27  
    28  type Builder interface {
    29  	Ext() string
    30  	New(w io.WriteCloser, conf Config) Archive
    31  	Coping(r *os.File, w io.Writer, conf Config) (Archive, error)
    32  }
    33  
    34  func Register(format string, obj Builder) {
    35  	builders[format] = obj
    36  }
    37  
    38  func UnRegister(format string) {
    39  	delete(builders, format)
    40  }
    41  
    42  func Support(format string) bool {
    43  	_, ok := builders[format]
    44  	return ok
    45  }
    46  
    47  func Ext(format string) string {
    48  	o, ok := builders[format]
    49  	if ok {
    50  		return o.Ext()
    51  	}
    52  	return ""
    53  }
    54  
    55  var builders = map[string]Builder{
    56  	"zip":    &zipBuilder{},
    57  	"tgz":    &tgzBuilder{ext: ".tgz"},
    58  	"tar.gz": &tgzBuilder{ext: ".tar.gz"},
    59  	"tar":    &tarBuilder{},
    60  	"gz":     &gzBuilder{},
    61  	"txz":    &txzBuilder{ext: ".txz"},
    62  	"tar.xz": &txzBuilder{ext: ".tar.xz"},
    63  	"7z":     &e7zBuilder{},
    64  }
    65  
    66  func NewBuilder(format string) Builder {
    67  	switch format {
    68  	case "zip":
    69  		return &zipBuilder{}
    70  	case "tgz":
    71  		return &tgzBuilder{ext: ".tgz"}
    72  	case "tar.gz":
    73  		return &tgzBuilder{ext: ".tar.gz"}
    74  	case "tar":
    75  		return &tarBuilder{}
    76  	case "gz":
    77  		return &gzBuilder{}
    78  	case "txz":
    79  		return &txzBuilder{ext: ".txz"}
    80  	case "tar.xz":
    81  		return &txzBuilder{ext: ".tar.xz"}
    82  	case "7z":
    83  		return &e7zBuilder{}
    84  	}
    85  	return nil
    86  }
    87  
    88  func NewMultiBuilder(ext string, objs ...Builder) Builder {
    89  	return &multiBuilder{
    90  		ext:  ext,
    91  		objs: append([]Builder{}, objs...),
    92  	}
    93  }
    94  
    95  type multiBuilder struct {
    96  	ext  string
    97  	objs []Builder
    98  }
    99  
   100  func (o *multiBuilder) Ext() string {
   101  	return o.ext
   102  }
   103  
   104  func (o *multiBuilder) New(w io.WriteCloser, conf Config) Archive {
   105  	var ars []Archive
   106  	for i := range o.objs {
   107  		ar := o.objs[i].New(w, conf)
   108  		ars = append(ars, ar)
   109  	}
   110  	return NewMulti(ars)
   111  }
   112  
   113  func (o *multiBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   114  	var ars []Archive
   115  	for i := range o.objs {
   116  		ar, err := o.objs[i].Coping(r, w, conf)
   117  		if err != nil {
   118  			ars = append(ars, ar)
   119  		}
   120  	}
   121  	return NewMulti(ars), nil
   122  }
   123  
   124  type e7zBuilder struct {
   125  }
   126  
   127  func (*e7zBuilder) Ext() string {
   128  	return ".7z"
   129  }
   130  
   131  func (*e7zBuilder) New(w io.WriteCloser, conf Config) Archive {
   132  	return e7z.New(w, conf.Path, conf.File)
   133  }
   134  
   135  func (*e7zBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   136  	return nil, fmt.Errorf("not support")
   137  }
   138  
   139  type zipBuilder struct {
   140  }
   141  
   142  func (*zipBuilder) Ext() string {
   143  	return ".zip"
   144  }
   145  func (*zipBuilder) New(w io.WriteCloser, conf Config) Archive {
   146  	return zip.New(w)
   147  }
   148  
   149  func (*zipBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   150  	return zip.Copying(r, w)
   151  }
   152  
   153  type tgzBuilder struct {
   154  	ext string
   155  }
   156  
   157  func (t *tgzBuilder) Ext() string {
   158  	return t.ext
   159  }
   160  func (*tgzBuilder) New(w io.WriteCloser, conf Config) Archive {
   161  	return targz.New(w)
   162  }
   163  
   164  func (*tgzBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   165  	return targz.Copying(r, w)
   166  }
   167  
   168  type tarBuilder struct {
   169  }
   170  
   171  func (t *tarBuilder) Ext() string {
   172  	return ".tar"
   173  }
   174  func (*tarBuilder) New(w io.WriteCloser, conf Config) Archive {
   175  	return tar.New(w)
   176  }
   177  
   178  func (*tarBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   179  	return tar.Copying(r, w)
   180  }
   181  
   182  type gzBuilder struct {
   183  }
   184  
   185  func (t *gzBuilder) Ext() string {
   186  	return ".gz"
   187  }
   188  func (*gzBuilder) New(w io.WriteCloser, conf Config) Archive {
   189  	return gzip.New(w)
   190  }
   191  
   192  func (*gzBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   193  	return nil, fmt.Errorf("not support")
   194  }
   195  
   196  type txzBuilder struct {
   197  	ext string
   198  }
   199  
   200  func (t *txzBuilder) Ext() string {
   201  	return t.ext
   202  }
   203  func (*txzBuilder) New(w io.WriteCloser, conf Config) Archive {
   204  	return tarxz.New(w)
   205  }
   206  
   207  func (*txzBuilder) Coping(r *os.File, w io.Writer, conf Config) (Archive, error) {
   208  	return nil, fmt.Errorf("not support")
   209  }
   210  
   211  // New archive.
   212  func New(w io.WriteCloser, conf Config) (Archive, error) {
   213  	if n, ok := builders[conf.Format]; ok {
   214  		return n.New(w, conf), nil
   215  	}
   216  	return nil, fmt.Errorf("invalid archive format: %s", conf.Format)
   217  }
   218  
   219  // Copying copies the source archive into a new one, which can be appended at.
   220  // Source needs to be in the specified format.
   221  func Copying(r *os.File, w io.Writer, conf Config) (Archive, error) {
   222  	if n, ok := builders[conf.Format]; ok {
   223  		return n.Coping(r, w, conf)
   224  	}
   225  	return nil, fmt.Errorf("invalid archive format: %s", conf.Format)
   226  }