github.phpd.cn/goreleaser/goreleaser@v0.92.0/internal/artifact/artifact.go (about) 1 // Package artifact provides the core artifact storage for goreleaser 2 package artifact 3 4 import ( 5 "crypto/sha256" 6 "encoding/hex" 7 "io" 8 "os" 9 "sync" 10 11 "github.com/apex/log" 12 "github.com/pkg/errors" 13 ) 14 15 // Type defines the type of an artifact 16 type Type int 17 18 const ( 19 // UploadableArchive a tar.gz/zip archive to be uploaded 20 UploadableArchive Type = iota 21 // UploadableBinary is a binary file to be uploaded 22 UploadableBinary 23 // Binary is a binary (output of a gobuild) 24 Binary 25 // LinuxPackage is a linux package generated by nfpm 26 LinuxPackage 27 // PublishableSnapcraft is a snap package yet to be published 28 PublishableSnapcraft 29 // Snapcraft is a published snap package 30 Snapcraft 31 // PublishableDockerImage is a Docker image yet to be published 32 PublishableDockerImage 33 // DockerImage is a published Docker image 34 DockerImage 35 // Checksum is a checksums file 36 Checksum 37 // Signature is a signature file 38 Signature 39 ) 40 41 func (t Type) String() string { 42 switch t { 43 case UploadableArchive: 44 return "Archive" 45 case UploadableBinary: 46 case Binary: 47 return "Binary" 48 case LinuxPackage: 49 return "Linux Package" 50 case DockerImage: 51 case PublishableDockerImage: 52 return "Docker Image" 53 case Checksum: 54 return "Checksum" 55 case Signature: 56 return "Signature" 57 } 58 return "unknown" 59 } 60 61 // Artifact represents an artifact and its relevant info 62 type Artifact struct { 63 Name string 64 Path string 65 Goos string 66 Goarch string 67 Goarm string 68 Type Type 69 Extra map[string]string 70 } 71 72 // Checksum calculates the SHA256 checksum of the artifact. 73 func (a Artifact) Checksum() (string, error) { 74 log.Debugf("calculating sha256sum for %s", a.Path) 75 file, err := os.Open(a.Path) 76 if err != nil { 77 return "", errors.Wrap(err, "failed to checksum") 78 } 79 defer file.Close() // nolint: errcheck 80 var hash = sha256.New() 81 _, err = io.Copy(hash, file) 82 if err != nil { 83 return "", errors.Wrap(err, "failed to checksum") 84 } 85 return hex.EncodeToString(hash.Sum(nil)), nil 86 } 87 88 // Artifacts is a list of artifacts 89 type Artifacts struct { 90 items []Artifact 91 lock *sync.Mutex 92 } 93 94 // New return a new list of artifacts 95 func New() Artifacts { 96 return Artifacts{ 97 items: []Artifact{}, 98 lock: &sync.Mutex{}, 99 } 100 } 101 102 // List return the actual list of artifacts 103 func (artifacts Artifacts) List() []Artifact { 104 return artifacts.items 105 } 106 107 // GroupByPlatform groups the artifacts by their platform 108 func (artifacts Artifacts) GroupByPlatform() map[string][]Artifact { 109 var result = map[string][]Artifact{} 110 for _, a := range artifacts.items { 111 plat := a.Goos + a.Goarch + a.Goarm 112 result[plat] = append(result[plat], a) 113 } 114 return result 115 } 116 117 // Add safely adds a new artifact to an artifact list 118 func (artifacts *Artifacts) Add(a Artifact) { 119 artifacts.lock.Lock() 120 defer artifacts.lock.Unlock() 121 log.WithFields(log.Fields{ 122 "name": a.Name, 123 "path": a.Path, 124 "type": a.Type, 125 }).Debug("added new artifact") 126 artifacts.items = append(artifacts.items, a) 127 } 128 129 // Filter defines an artifact filter which can be used within the Filter 130 // function 131 type Filter func(a Artifact) bool 132 133 // ByGoos is a predefined filter that filters by the given goos 134 func ByGoos(s string) Filter { 135 return func(a Artifact) bool { 136 return a.Goos == s 137 } 138 } 139 140 // ByGoarch is a predefined filter that filters by the given goarch 141 func ByGoarch(s string) Filter { 142 return func(a Artifact) bool { 143 return a.Goarch == s 144 } 145 } 146 147 // ByGoarm is a predefined filter that filters by the given goarm 148 func ByGoarm(s string) Filter { 149 return func(a Artifact) bool { 150 return a.Goarm == s 151 } 152 } 153 154 // ByType is a predefined filter that filters by the given type 155 func ByType(t Type) Filter { 156 return func(a Artifact) bool { 157 return a.Type == t 158 } 159 } 160 161 // Or performs an OR between all given filters 162 func Or(filters ...Filter) Filter { 163 return func(a Artifact) bool { 164 for _, f := range filters { 165 if f(a) { 166 return true 167 } 168 } 169 return false 170 } 171 } 172 173 // And performs an AND between all given filters 174 func And(filters ...Filter) Filter { 175 return func(a Artifact) bool { 176 for _, f := range filters { 177 if !f(a) { 178 return false 179 } 180 } 181 return true 182 } 183 } 184 185 // Filter filters the artifact list, returning a new instance. 186 // There are some pre-defined filters but anything of the Type Filter 187 // is accepted. 188 // You can compose filters by using the And and Or filters. 189 func (artifacts *Artifacts) Filter(filter Filter) Artifacts { 190 var result = New() 191 for _, a := range artifacts.items { 192 if filter(a) { 193 result.items = append(result.items, a) 194 } 195 } 196 return result 197 }