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 }