Created
August 14, 2020 02:21
-
-
Save 17twenty/c492d9d75f1656385101446b22042b0c to your computer and use it in GitHub Desktop.
Generate an embeddable zip file that can be included in your Golang project that auto extracts at runtime.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io/ioutil" | |
"os" | |
"strings" | |
) | |
func main() { | |
//Empty string slice to place the byte lierals in | |
var dataSlice []string | |
if len(os.Args) != 4 { | |
fmt.Println("usage:") | |
fmt.Println(os.Args[0], "<sourcefile> <generated_file.go> <extraction_target>") | |
os.Exit(1) | |
} | |
//This will be the generated go file | |
//Note: the path is ./ because we are using the go generate command | |
// inside the main.go file | |
outfile, err := os.Create(os.Args[2]) | |
if err != nil { | |
panic(err.Error()) | |
} | |
defer outfile.Close() | |
//This is the file we will turn to []bytes | |
//Make sure you use the name you used to build the sample data | |
infile, err := ioutil.ReadFile(os.Args[1]) | |
if err != nil { | |
panic(err.Error()) | |
} | |
//Write the initial data to the generated go file | |
//package main | |
//var data = []byte{ EOF... so far | |
outfile.Write([]byte(fmt.Sprintf(`package main | |
//Do not edit this file, it is auto generated | |
import "os" | |
func init() { | |
//Create the binary file | |
file, err := os.Create("%s") | |
if err != nil { | |
return | |
} | |
defer file.Close() | |
//Write the data to the the created file | |
file.Write(bindata) | |
} | |
// Byte data | |
var ( | |
bindata = []byte{`, os.Args[3]))) | |
//Here we loop over each byte in the []byte from the sample | |
//data file. | |
//Take the byte literal and format it as a string | |
//Then append it to the empty []string dataSlice we created at | |
//the top of the func | |
//Depending on the size of infile this could take a bit | |
for _, b := range infile { | |
bString := fmt.Sprintf("%v", b) | |
dataSlice = append(dataSlice, bString) | |
} | |
//We join the []string together separating it with commas | |
//Remember we are writing a go src file so everything has to be a string | |
dataString := strings.Join(dataSlice, ", ") | |
//Write all the data to the generated file | |
outfile.WriteString(dataString) | |
//Finish off the data | |
outfile.Write([]byte("}\n)")) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package anotherpackage | |
import ( | |
"archive/zip" | |
"fmt" | |
"io" | |
"os" | |
"path/filepath" | |
"strings" | |
) | |
// Create our archive | |
//go:generate zip -r /tmp/migrate-out.zip migrations | |
//go:generate go run ./generator/cmd/generator.go /tmp/migrate-out.zip migrations_generated.go /tmp/migrate.zip | |
... | |
func main() { | |
... | |
if files, err := unzip("/tmp/migrate.zip", "/tmp/"); err == nil { | |
log.Println("Zip found, unzipped") | |
for f := range files { | |
log.Println(" ", files[f]) | |
} | |
} | |
... | |
} | |
// within the zip file (parameter 1) to an output directory (parameter 2). | |
func unzip(src string, dest string) ([]string, error) { | |
var filenames []string | |
r, err := zip.OpenReader(src) | |
if err != nil { | |
return filenames, err | |
} | |
defer r.Close() | |
for _, f := range r.File { | |
// Store filename/path for returning and using later on | |
fpath := filepath.Join(dest, f.Name) | |
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE | |
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) { | |
return filenames, fmt.Errorf("%s: illegal file path", fpath) | |
} | |
filenames = append(filenames, fpath) | |
if f.FileInfo().IsDir() { | |
// Make Folder | |
os.MkdirAll(fpath, os.ModePerm) | |
continue | |
} | |
// Make File | |
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { | |
return filenames, err | |
} | |
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) | |
if err != nil { | |
return filenames, err | |
} | |
rc, err := f.Open() | |
if err != nil { | |
return filenames, err | |
} | |
_, err = io.Copy(outFile, rc) | |
// Close the file without defer to close before next iteration of loop | |
outFile.Close() | |
rc.Close() | |
if err != nil { | |
return filenames, err | |
} | |
} | |
return filenames, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment