main.go (4101B)
1 // build functions as a build script, building and bundling the package. 2 package main 3 4 import ( 5 "archive/zip" 6 "bytes" 7 "flag" 8 "fmt" 9 "image/png" 10 "io" 11 "log" 12 "net/http" 13 "os" 14 "path/filepath" 15 "runtime" 16 "strings" 17 18 "github.com/jackmordaunt/icns" 19 "github.com/pkg/errors" 20 ) 21 22 var ( 23 dist string 24 tags string 25 icon string 26 ui string 27 ffmpeg string 28 ) 29 30 func init() { 31 flag.StringVar(&dist, "dist", "dist", "folder to put artifact") 32 flag.StringVar(&icon, "icon", icon, "path to icon file (.png or .icns)") 33 flag.StringVar(&tags, "tags", tags, "build tags to pass to go build") 34 flag.StringVar(&ffmpeg, "ffmpeg", ffmpeg, "path to ffmpeg binary") 35 flag.StringVar(&ui, "ui", ui, "path to UI files") 36 flag.Parse() 37 } 38 39 func main() { 40 switch runtime.GOOS { 41 case "darwin": 42 builder := &Darwin{ 43 Bin: "giffer", 44 Pkg: "github.com/jackmordaunt/giffer/cmd/desktop", 45 UI: ui, 46 Icon: icon, 47 FFmpeg: ffmpeg, 48 BuildTags: tags, 49 } 50 if err := builder.Build(dist); err != nil { 51 log.Fatalf("building Giffer for MacOS: %v", err) 52 } 53 case "windows": 54 builder := &Windows{ 55 Bin: "giffer.exe", 56 Pkg: "github.com/jackmordaunt/giffer/cmd/desktop", 57 UI: ui, 58 Icon: icon, 59 FFmpeg: ffmpeg, 60 BuildTags: tags, 61 } 62 if err := builder.Build(dist); err != nil { 63 log.Fatalf("building Giffer for Windows: %v", err) 64 } 65 default: 66 log.Fatalf("OS %s is not supported", runtime.GOOS) 67 } 68 69 } 70 71 // WriteIcon writes out the icon.icns using specified source icon. 72 // If the source icon is a .png then it is converted to .icns. 73 func WriteIcon(in, out string) error { 74 var ( 75 src io.ReadWriter 76 ext = filepath.Ext(in) 77 ) 78 if ext != ".png" && ext != ".icns" { 79 return fmt.Errorf("icon must be .icns or .png: %s", icon) 80 } 81 inf, err := os.Open(in) 82 if err != nil { 83 return errors.Wrap(err, "opening input file") 84 } 85 defer inf.Close() 86 src = inf 87 if ext == ".png" { 88 img, err := png.Decode(inf) 89 if err != nil { 90 return errors.Wrap(err, "decoding png") 91 } 92 buf := bytes.NewBuffer(nil) 93 if err := icns.Encode(buf, img); err != nil { 94 return errors.Wrap(err, "encoding icns") 95 } 96 src = buf 97 } 98 outf, err := os.Create(out) 99 if err != nil { 100 return errors.Wrap(err, "creating output file") 101 } 102 defer outf.Close() 103 if _, err := io.Copy(outf, src); err != nil { 104 return err 105 } 106 return nil 107 } 108 109 // openZip returns the first file in the zip that contains the pattern. 110 func openZip(u, dir, pattern string) (*bytes.Buffer, error) { 111 file, err := download(u, filepath.Join(dir, "ffmpeg.zip")) 112 if err != nil { 113 return nil, errors.Wrap(err, "downloading") 114 } 115 defer file.Close() 116 info, err := file.Stat() 117 if err != nil { 118 return nil, errors.Wrap(err, "getting file info") 119 } 120 zr, err := zip.NewReader(file, info.Size()) 121 if err != nil { 122 return nil, errors.Wrap(err, "creating zip reader") 123 } 124 for _, zf := range zr.File { 125 if strings.Contains(zf.Name, pattern) { 126 var buf = bytes.NewBuffer(nil) 127 zfr, err := zf.Open() 128 if err != nil { 129 return nil, errors.Wrap(err, "reading zipped file") 130 } 131 defer zfr.Close() 132 if _, err := io.Copy(buf, zfr); err != nil { 133 return nil, errors.Wrap(err, "buffering zipped file") 134 } 135 return buf, nil 136 } 137 } 138 return nil, fmt.Errorf("no file found in zip for given pattern %q", pattern) 139 } 140 141 // download the file at the specified url. 142 // If a file exists at dst, that file is returned. 143 func download(u, dst string) (*os.File, error) { 144 dstf, err := os.Open(dst) 145 if err != nil && !os.IsNotExist(err) { 146 return nil, errors.Wrap(err, "opening downloaded file") 147 } 148 if err == nil { 149 return dstf, nil 150 } 151 resp, err := http.Get(u) 152 if err != nil { 153 return nil, errors.Wrap(err, "GET") 154 } 155 defer resp.Body.Close() 156 if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) { 157 return nil, fmt.Errorf("status %d", resp.StatusCode) 158 } 159 zipf, err := os.Create(dst) 160 if err != nil { 161 return nil, errors.Wrap(err, "creating destination file") 162 } 163 if _, err := io.Copy(zipf, resp.Body); err != nil { 164 return nil, errors.Wrap(err, "copying body") 165 } 166 return zipf, nil 167 }