Exemple #1
0
func Compile() gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				buff := new(bytes.Buffer)
				name := strings.TrimSuffix(file.FileInfo().Name(), ".gcss") + ".css"
				ctx.Infof("Compiling %s to %s", file.FileInfo().Name(), name)
				n, err := gcss.Compile(buff, file)
				if err != nil {
					return err
				}

				file = gonzo.NewFile(ioutil.NopCloser(buff), file.FileInfo())
				file.FileInfo().SetSize(int64(n))
				file.FileInfo().SetName(name)

				out <- file
			case <-ctx.Done():
				return nil
			}
		}
	}
}
Exemple #2
0
// Untar files from input channel and pass the result
// to the output channel.
func Uncompress() gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				content, err := gzip.NewReader(file)
				if err != nil {
					return err
				}

				fs := gonzo.NewFile(
					&doublecloser{content, file.Close},
					gonzo.FileInfoFrom(file.FileInfo()),
				)

				out <- fs
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #3
0
func Minify() gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				buff := new(bytes.Buffer)
				name := strings.TrimSuffix(file.FileInfo().Name(), ".css") + ".min.css"
				ctx.Infof("Compiling %s to %s", file.FileInfo().Name(), name)
				m := minify.New()
				m.AddFunc("text/css", css.Minify)
				err := m.Minify("text/css", buff, file)
				if err != nil {
					return err
				}

				file = gonzo.NewFile(ioutil.NopCloser(buff), file.FileInfo())
				file.FileInfo().SetSize(int64(buff.Len()))
				file.FileInfo().SetName(name)

				out <- file
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
func Compile(conf Config) gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		b := cache{conf, make(map[string]gonzo.File)}

		for file := range in {
			path := file.FileInfo().Name()
			ctx.Infof("Adding %s", path)
			b.Files[path] = file
			defer file.Close() //Close files AFTER we have build our package.
		}

		buff := new(bytes.Buffer)
		err := cacheTemplate.Execute(buff, b)
		if err != nil {
			ctx.Error(err)
			return err
		}

		fi := gonzo.NewFileInfo()
		fi.SetName(b.Name)
		fi.SetSize(int64(buff.Len()))
		sf := gonzo.NewFile(ioutil.NopCloser(buff), fi)

		out <- sf
		return nil
	}
}
Exemple #5
0
func Compile() gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {
		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				source, err := ioutil.ReadAll(file)
				if err != nil {
					return err
				}

				dc := sass.NewDataContext(string(source))
				defer dc.Destroy()
				opts := dc.Context().Options()

				base := filepath.Join(
					file.FileInfo().Base(),
					filepath.Dir(file.FileInfo().Name()),
				)

				opts.SetIncludePath(base)

				compiler := dc.Compiler()
				defer compiler.Destroy()

				err = compiler.Parse()
				if err != nil {
					ctx.Error(err)
					//ctx.Error(dc.Context().Error().Error())
					return errors.New(dc.Context().Error().Error())
				}

				err = compiler.Execute()
				if err != nil {
					ctx.Error(err)
					return errors.New(dc.Context().Error().Error())
				}

				output := dc.Context().OutputString()

				buff := bytes.NewBufferString(output)

				name := strings.TrimSuffix(file.FileInfo().Name(), ".scss") + ".css"

				ctx.Infof("Compiling %s to %s", file.FileInfo().Name(), name)

				file = gonzo.NewFile(ioutil.NopCloser(buff), file.FileInfo())
				file.FileInfo().SetSize(int64(buff.Len()))
				file.FileInfo().SetName(name)

				out <- file
			case <-ctx.Done():
				return nil
			}
		}
	}
}
Exemple #6
0
// bin is the binary name, it will be passed to os/exec.Command, so the same
// path rules applies.
// the args are the argumetns passed to the program.
func Run(bin string, args ...string) gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				cmd := exec.Command(bin, args...)
				cmd.Stderr = os.Stderr //TODO: io.Writer logger.
				cmd.Stdin = file

				ctx = context.WithValue(ctx, "cmd", bin)
				ctx.Infof("Passing %s", file.FileInfo().Name())

				output, err := cmd.Output()
				if err != nil {
					return err
				}

				content := ioutil.NopCloser(bytes.NewReader(output))
				out <- gonzo.NewFile(content, file.FileInfo())

			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #7
0
// Untar files from input channel and pass the result to the output channel.
func Untar(opt Options) gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		//Check patterns.
		pluck := len(opt.Pluck) > 0
		if pluck {
			err := match.Good(opt.Pluck...)
			if err != nil {
				return err
			}
		}

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				context.WithValue(ctx, "archive", file.FileInfo().Name()).Debug("Untaring")
				tr := tar.NewReader(file)
				defer file.Close()

				// Iterate through the files in the archive.
				for {
					hdr, err := tr.Next()
					if err == io.EOF {
						// end of tar archive
						break
					}
					if err != nil {
						return err
					}

					name := strip(opt.StripComponenets, hdr.Name)
					if pluck && !match.Any(name, opt.Pluck...) {
						continue
					}

					context.WithValue(ctx, "file", name).Debug("Untaring")

					content := new(bytes.Buffer)
					n, err := content.ReadFrom(tr)
					if err != nil {
						return err
					}
					fs := gonzo.NewFile(ioutil.NopCloser(content), gonzo.FileInfoFrom(hdr.FileInfo()))
					fs.FileInfo().SetName(name)
					fs.FileInfo().SetSize(int64(n))

					out <- fs
				}
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #8
0
// A build stage creates a new Package and adds all the files coming through the channel to
// the package and returns the result of build as a File on the output channel.
func Build(config Config) gonzo.Stage {
	return func(ctx context.Context, files <-chan gonzo.File, out chan<- gonzo.File) error {

		ctx, cancel := context.WithCancel(ctx)

		res := resources.New()
		res.Config = resources.Config(config)

		var err error

		buff := &bytes.Buffer{}
		for {
			select {
			case file, ok := <-files:
				if !ok {
					goto BUILD
				}

				if file.FileInfo().IsDir() {
					continue
				}
				path, _ := filepath.Rel(file.FileInfo().Base(), file.FileInfo().Name())
				res.Add(filepath.ToSlash(path), file)
				ctx.Infof("Adding %s", path)
				defer func(path string) {
					ctx.Debug("Closing %s", path)
					file.Close() //Close files AFTER we have build our package.
				}(path)
			case <-ctx.Done():
				err = ctx.Err()
				goto BUILD
			}
		}

	BUILD:
		if err != nil {
			return err
		}

		ctx.Debug("Runnig build...")
		err = res.Build(buff)
		if err != nil {
			cancel()
			return err
		}
		path := fmt.Sprintf(FilenameFormat, strings.ToLower(config.Var))
		sf := gonzo.NewFile(ioutil.NopCloser(buff), gonzo.NewFileInfo())
		sf.FileInfo().SetName(path)
		sf.FileInfo().SetSize(int64(buff.Len()))
		out <- sf
		return nil
	}
}
Exemple #9
0
func Put(c Config) gonzo.Stage {
	return func(ctx context.Context, files <-chan gonzo.File, out chan<- gonzo.File) error {

		err := checkconfig(c)
		if err != nil {
			return err
		}

		auth := aws.Auth{
			AccessKey: c.AccessKey,
			SecretKey: c.SecretKey,
		}

		con := s3.New(auth, aws.Region(c.Region))
		bucket := con.Bucket(c.Name)

		for {
			select {
			case file, ok := <-files:
				if !ok {
					return nil
				}
				if file.FileInfo().IsDir() {
					continue
				}

				content, err := ioutil.ReadAll(file)
				if err != nil {
					return err
				}

				name := file.FileInfo().Name()

				contentType := mime.TypeByExtension(filepath.Ext(name))
				if contentType == "" {
					contentType = http.DetectContentType(content)
				}
				ctx = context.WithValue(ctx, "Content-Type", contentType)
				ctx.Infof("Uploading %s", name)

				err = bucket.Put(name, content, contentType, s3.ACL(c.Perm))
				if err != nil {
					return err
				}

				out <- gonzo.NewFile(ioutil.NopCloser(bytes.NewReader(content)), file.FileInfo())
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #10
0
// Concatenates all the files from the input channel
// and passes them to output channel with the given name.
func Concat(ctx context.Context, name string) gonzo.Stage {
	return func(ctx context.Context, files <-chan gonzo.File, out chan<- gonzo.File) error {

		var (
			size    int64
			bigfile = new(bytes.Buffer)
		)

		err := func() error {
			for {
				select {
				case f, ok := <-files:
					if !ok {
						return nil
					}

					ctx.Infof(
						"Adding %s to %s",
						filepath.Join(f.FileInfo().Base(), f.FileInfo().Name()),
						name,
					)

					n, err := bigfile.ReadFrom(f)
					if err != nil {
						return err
					}
					bigfile.WriteRune('\n')
					size += n + 1

					f.Close()
				case <-ctx.Done():
					return ctx.Err()
				}
			}
		}()

		if err != nil {
			return err
		}

		file := gonzo.NewFile(ioutil.NopCloser(bigfile), gonzo.NewFileInfo())
		file.FileInfo().SetSize(size)
		file.FileInfo().SetName(name)
		out <- file
		return nil
	}
}
Exemple #11
0
// A simple helper function that opens the file from the given path and
// returns a pointer to a gonzo.File or an error.
func Read(path string) (gonzo.File, error) {
	Stat, err := os.Stat(path)
	if err != nil {
		return nil, err
	}

	if Stat.IsDir() {
		return nil, ErrIsDir
	}

	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}

	return gonzo.NewFile(f, gonzo.FileInfoFrom(Stat)), nil
}
Exemple #12
0
// Unzip the zip files from input channel and pass the result
// to the output channel.
func Unzip() gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				raw, err := ioutil.ReadAll(file)
				if err != nil {
					return err
				}
				file.Close()

				r, err := zip.NewReader(bytes.NewReader(raw), int64(len(raw)))
				if err != nil {
					return err
				}

				//counter := c.Counter("unzipping", len(r.File))

				// Iterate through the files in the archive,
				for _, f := range r.File {
					ctx = context.WithValue(ctx, "file", f.Name)
					ctx.Info("Unziping")
					//counter.Set(i+1, f.Name)

					content, err := f.Open()
					if err != nil {
					}
					fs := gonzo.NewFile(content, gonzo.FileInfoFrom(f.FileInfo()))
					fs.FileInfo().SetName(f.Name)

					out <- fs
				}
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #13
0
// Dest writes the files from the input channel to the dst folder and closes the files.
// It never returns Files.
func Dest(dst string) gonzo.Stage {
	return func(ctx context.Context, files <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-files:
				if !ok {
					return nil
				}

				name := file.FileInfo().Name()
				path := filepath.Join(dst, filepath.Dir(name))
				err := os.MkdirAll(path, 0700)
				if err != nil {
					return err
				}

				if file.FileInfo().IsDir() {
					out <- file
					continue
				}

				content, err := ioutil.ReadAll(file)
				if err != nil {
					file.Close()
					return err
				}

				ctx = context.WithValue(ctx, "path", path)
				ctx.Infof("Writing %s", name)
				err = writeFile(filepath.Join(dst, name), content)
				if err != nil {
					return err
				}

				out <- gonzo.NewFile(ioutil.NopCloser(bytes.NewReader(content)), file.FileInfo())

			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #14
0
func get(ctx context.Context, client *http.Client, url string) (gonzo.File, error) {

	resp, err := ctxhttp.Get(ctx, client, url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode < 200 || resp.StatusCode > 399 {
		return nil, fmt.Errorf("%s (%s)", resp.Status, url)
	}

	_, params, err := mime.ParseMediaType(resp.Header.Get("Content-Disposition"))
	name, ok := params["filename"]
	if !ok || err != nil {
		name = path.Base(url)
	}

	file := gonzo.NewFile(resp.Body, gonzo.NewFileInfo())
	file.FileInfo().SetName(name)
	file.FileInfo().SetSize(resp.ContentLength)

	return file, nil
}
Exemple #15
0
func Minify(opt Options) gonzo.Stage {

	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				buff := new(bytes.Buffer)
				ctx.Infof("Minfiying %s", file.FileInfo().Name())
				m := minify.New()
				m.Add("text/html", &html.Minifier{
					KeepDefaultAttrVals: opt.KeepDefaultAttrVals,
					KeepWhitespace:      opt.KeepWhitespace,
				})
				m.AddFunc("text/css", css.Minify)
				m.AddFunc("text/javascript", js.Minify)
				m.AddFunc("image/svg+xml", svg.Minify)

				err := m.Minify("text/html", buff, file)
				if err != nil {
					return err
				}

				file = gonzo.NewFile(ioutil.NopCloser(buff), file.FileInfo())
				file.FileInfo().SetSize(int64(buff.Len()))

				out <- file
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	}
}
Exemple #16
0
func Compile(options Options, data interface{}) gonzo.Stage {
	return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error {

		options := ace.Options(options)

		fs := []*ace.File{}

		for {
			select {
			case file, ok := <-in:
				if !ok {
					return nil
				}

				buf := new(bytes.Buffer)
				_, err := buf.ReadFrom(file)
				file.Close()
				if err != nil {
					ctx.Error(err)
					continue
				}

				s, err := file.Stat()
				if err != nil {
					return err
				}

				name := s.Name() //Probably filepath.Rel(file.Dir, file.Path) ??
				f := ace.NewFile(name, buf.Bytes())
				source := ace.NewSource(
					ace.NewFile("", nil),
					f,
					fs,
				)

				fs = append(fs, f)

				r, err := ace.ParseSource(source, &options)
				if err != nil {
					ctx.Error(err)
					continue
				}

				t, err := ace.CompileResultWithTemplate(html.New(name), r, &options)
				if err != nil {
					ctx.Error(err)
					continue
				}

				if filepath.Base(file.FileInfo().Name())[0] != '_' {
					buf := new(bytes.Buffer)
					err = t.Execute(buf, data)
					if err != nil {
						ctx.Error(err)
						continue
					}

					file = gonzo.NewFile(ioutil.NopCloser(buf), file.FileInfo())
					file.FileInfo().SetSize(int64(buf.Len()))
					name = strings.TrimSuffix(file.FileInfo().Name(), ".ace") + ".html"
					file.FileInfo().SetName(name)
				}

				out <- file

			case <-ctx.Done():
				return ctx.Err()
			}
			return nil
		}
	}
}