Skip to content
Permalink
Browse files

upload

  • Loading branch information
jaddr2line committed Jun 25, 2017
0 parents commit 31ed20b01f35ea8d3f046679bc36a52f9cf9608d
Showing with 390 additions and 0 deletions.
  1. +11 −0 Dockerfile
  2. +2 −0 Makefile
  3. +229 −0 pacgen.go
  4. +61 −0 pacgen_test.go
  5. +6 −0 script/Makefile
  6. +41 −0 script/build.sh
  7. +8 −0 script/convert/Makefile
  8. +32 −0 script/convert/convert.go
@@ -0,0 +1,11 @@
FROM golang:1.8-alpine

ADD . /build

WORKDIR /build

RUN apk add --no-cache git make bash curl

RUN make install

ENTRYPOINT ["/bin/buildpkg"]
@@ -0,0 +1,2 @@
install:
$(MAKE) -C script install
229 pacgen.go
@@ -0,0 +1,229 @@
package panuxpackager

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"text/template"

"github.com/hashicorp/go-version"
"gopkg.in/yaml.v2"
)

//RawPackageGenerator represents a PackageGenerator parsed from YAML
type RawPackageGenerator struct {
Tools []string
Version string
Sources []string
Script []string
Dependencies []string
BuildDependencies []string
Data map[string]interface{}
}

//ParseRaw parses a RawPackageGenerator from data in a []byte
func ParseRaw(in []byte) (pg RawPackageGenerator, err error) {
err = yaml.Unmarshal(in, &pg)
if err != nil {
pg = RawPackageGenerator{}
}
return
}

//Tool is a tool for a PackageGenerator
type Tool struct {
Name string
Version *version.Version
ToolFuncs map[string]func() (interface{}, error)
Dependencies []string
}

var tools map[string]*Tool

//PackageGenerator is a preprocessed package generator
type PackageGenerator struct {
Tools []*Tool
Version *version.Version
Sources []*url.URL
Script string
Dependencies []string
BuildDependencies []string
}

func (pg PackageGenerator) toolfuncs() (m map[string]interface{}) {
m = make(map[string]interface{})
for _, v := range pg.Tools {
for n, t := range v.ToolFuncs {
m[n] = t
}
}
return
}

//Preprocess runs preprocessing steps on the RawPackageGenerator in order to convert it to a PackageGenerator
func (r RawPackageGenerator) Preprocess() (pg PackageGenerator, err error) {
npg := PackageGenerator{}
for _, name := range r.Tools {
tool := tools[name]
if tool == nil {
return npg, fmt.Errorf("Tool %q not found", name)
}
}
tf := pg.toolfuncs()
pg.Version, err = version.NewVersion(r.Version)
if err != nil {
return npg, err
}
pg.Sources = make([]*url.URL, len(r.Sources))
for i, v := range r.Sources {
tmpl, err := template.New("sources").Parse(v)
if err != nil {
return npg, err
}
tmpl.Funcs(tf)
buf := bytes.NewBuffer(nil)
err = tmpl.Execute(buf, r)
if err != nil {
return npg, err
}
sstr := buf.String()
src, err := url.Parse(sstr)
if err != nil {
return npg, err
}
pg.Sources[i] = src
}
pg.BuildDependencies = make([]string, len(r.BuildDependencies))
for i, v := range r.BuildDependencies {
tmpl, err := template.New("build_dependencies").Parse(v)
if err != nil {
return npg, err
}
tmpl.Funcs(tf)
buf := bytes.NewBuffer(nil)
err = tmpl.Execute(buf, r)
if err != nil {
return npg, err
}
pg.BuildDependencies[i] = buf.String()
}
for _, v := range pg.Tools {
if v.Dependencies != nil {
pg.BuildDependencies = append(pg.BuildDependencies, v.Dependencies...)
}
}
pg.Dependencies = make([]string, len(r.Dependencies))
for i, v := range r.BuildDependencies {
tmpl, err := template.New("dependencies").Parse(v)
if err != nil {
return npg, err
}
tmpl.Funcs(tf)
buf := bytes.NewBuffer(nil)
err = tmpl.Execute(buf, r)
if err != nil {
return npg, err
}
pg.Dependencies[i] = buf.String()
}
stmpl, err := template.New("script").Parse(strings.Join(r.Script, "\n"))
if err != nil {
return npg, err
}
stmpl.Funcs(tf)
buf := bytes.NewBuffer(nil)
err = stmpl.Execute(buf, r)
if err != nil {
return npg, err
}
pg.Script = buf.String()
return
}

//InitDir initializes a directory for generating the package
func (pg PackageGenerator) InitDir(path string) error {
//Make workdir structure
srcpath := filepath.Join(path, "src")
outpath := filepath.Join(path, "out")
err := os.Mkdir(srcpath, os.ModePerm)
if err != nil {
return err
}
err = os.Mkdir(outpath, os.ModePerm)
if err != nil {
return err
}
//Download sources (in parallell)
cmpl := make(chan error)
for _, v := range pg.Sources {
chk := func(err error) {
if err != nil {
panic(err)
}
}
getaddr := v.String()
gpath := v.Path
go func() {
defer func() { recover() }() //recover any error from termination
defer func() {
err := recover()
if err != nil {
cmpl <- err.(error)
} else {
cmpl <- nil
}
}()
log.Printf("Downloading %s\n", getaddr)
g, err := http.Get(getaddr)
chk(err)
defer func() { chk(g.Body.Close()) }()
faddr := filepath.Join(srcpath, ""+filepath.Base(gpath))
f, err := os.OpenFile(faddr, os.O_CREATE|os.O_WRONLY, 0644)
chk(err)
defer func() { chk(f.Close()) }()
_, err = io.Copy(f, g.Body)
chk(err)
}()
}
n := len(pg.Sources)
for n > 0 {
err := <-cmpl
if err != nil {
close(cmpl)
return err
}
n--
}
//Write script to file
spath := filepath.Join(path, "script.sh")
err = ioutil.WriteFile(spath, []byte(pg.Script), 0700)
if err != nil {
return err
}
//Write dependencies to file
dpath := filepath.Join(outpath, ".deps.list")
err = ioutil.WriteFile(dpath, []byte(strings.Join(pg.Dependencies, "\n")), 0700)
if err != nil {
return err
}
//Write build-dependencies to file
bdpath := filepath.Join(path, ".builddeps.list")
err = ioutil.WriteFile(bdpath, []byte(strings.Join(pg.BuildDependencies, "\n")), 0700)
if err != nil {
return err
}
//Write version to file
vpath := filepath.Join(outpath, ".version")
err = ioutil.WriteFile(vpath, []byte(pg.Version.String()), 0700)
if err != nil {
return err
}
return nil
}
@@ -0,0 +1,61 @@
package panuxpackager

import (
"encoding/json"
"testing"
)

func TestParseRaw(t *testing.T) {
teststring := `
tools:
- Apple
- Pear
version: v1.0
sources:
- https://example.com/source1
- https://example.com/source2
script:
- echo "Hello world"
- cat example.txt
`
pg, err := ParseRaw([]byte(teststring))
if err != nil {
t.Fatal(err)
}
expected := RawPackageGenerator{
Tools: []string{
"Apple",
"Pear",
},
Version: "v1.0",
Sources: []string{
"https://example.com/source1",
"https://example.com/source2",
},
Script: []string{
"echo \"Hello world\"",
"cat example.txt",
},
}
a, err := json.Marshal(pg)
if err != nil {
t.Fatal("Failed to check results")
}
b, err := json.Marshal(expected)
if err != nil {
t.Fatal("Failed to check results")
}
if string(a) != string(b) {
t.Fatal("incorrect unmarshal")
}
}

func TestBadParse(t *testing.T) {
pg, err := ParseRaw([]byte("This should return an error"))
if err == nil {
t.Fatal("Test should have returned error but did not")
}
if pg.Script != nil || pg.Sources != nil || pg.Tools != nil || pg.Version != "" {
t.Fatal("Did not return empty RawPackageGenerator on error")
}
}
@@ -0,0 +1,6 @@
pkgenconvert:
$(MAKE) -C convert

install: pkgenconvert
$(MAKE) -C convert install
install -m 0700 build.sh /bin/buildpkg
@@ -0,0 +1,41 @@
#!/bin/bash

if [ "$#" -ne 1 ] || ! [ -e "$1" ]; then
echo "Script takes one argument, which is a package generator file name"
fi

if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi

DIR=$(mktemp -d)

function cleanup {
rm -rf $DIR
}
trap cleanup EXIT

echo "Parsing PackageGenerator and downloading files"
pkgenconvert -in $1 -dir $DIR

#currently using alpine docker containers
apk add --no-cache $(cat $DIR/.builddeps.list)

echo "Done preparing"

#run build in a subshell
echo "Starting build. . . "
(
cd $DIR
bash script.sh
)
echo "Build complete"

echo "Tarring output"
OUT=$(mktemp).tar.xz
tar -cvf $OUT -C $DIR/out .

UPLOAD=$(curl --upload-file $OUT https://transfer.sh/pkg.tar.xz)

echo $UPLOAD
@@ -0,0 +1,8 @@
godeps:
go get github.com/hashicorp/go-version gopkg.in/yaml.v2

pkgenconvert: godeps
go build -o pkgenconvert

install: pkgenconvert
install -m 0700 pkgenconvert /bin/pkgenconvert
@@ -0,0 +1,32 @@
package main

import (
"flag"
"fmt"
"io/ioutil"

"../.."
)

func chk(err error) {
if err != nil {
panic(err)
}
}

func main() {
var dir string
var infile string
flag.StringVar(&infile, "in", "", "input file to generate from")
flag.StringVar(&dir, "dir", "", "directory to generate into")
flag.Parse()
dat, err := ioutil.ReadFile(infile)
chk(err)
fmt.Println(string(dat))
r, err := panuxpackager.ParseRaw(dat)
chk(err)
fmt.Println(r)
pg, err := r.Preprocess()
chk(err)
chk(pg.InitDir(dir))
}

0 comments on commit 31ed20b

Please sign in to comment.
You can’t perform that action at this time.