Пример #1
0
// Load the caches from a file.
func Load() error {
	conf := config.Current()
	filename := filepath.Join(conf.Build, CACHE_FILENAME)

	if config.NoCache {
		return nil
	}

	f, err := os.Open(filename)
	if err != nil && os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	log.Println("Reading cache:", filename)

	d := gob.NewDecoder(f)
	if err := d.Decode(&modificationCache); err != nil {
		return app.Error(err)
	}
	if err := d.Decode(&dataCache); err != nil {
		return app.Error(err)
	}

	log.Println("Read", len(modificationCache), "modifications and", len(dataCache), "datas!")

	return nil
}
Пример #2
0
func copyFiles(from []string, to string) error {
	srcs := []io.Reader{}
	for _, f := range from {
		src, err := os.Open(f)
		if err != nil {
			return app.Error(err)
		}
		defer src.Close()

		srcs = append(srcs, src)
	}

	src := io.MultiReader(srcs...)

	dest, err := os.Create(to)
	if err != nil {
		return app.Error(err)
	}
	defer dest.Close()

	if _, err = io.Copy(dest, src); err != nil {
		return app.Error(err)
	}

	return nil
}
Пример #3
0
func Input(r *app.Request) error {
	name := mux.Vars(r.Req)["name"]

	if name == config.DEPS_NAME {
		if err := hooks.PreCompile(); err != nil {
			return err
		}

		if err := soy.Compile(); err != nil {
			return err
		}

		if _, _, err := js.GenerateDeps("input"); err != nil {
			return err
		}

		conf := config.Current()
		f, err := os.Open(path.Join(conf.Build, config.DEPS_NAME))
		if err != nil {
			return app.Error(err)
		}
		defer f.Close()

		r.W.Header().Set("Content-Type", "text/javascript")
		if _, err := io.Copy(r.W, f); err != nil {
			return app.Error(err)
		}

		if err := hooks.PostCompile(); err != nil {
			return err
		}

		return nil
	}

	// Otherwise serve the file if it can be found
	paths := scan.BaseJSPaths()
	for _, p := range paths {
		f, err := os.Open(path.Join(p, name))
		if err != nil && !os.IsNotExist(err) {
			return app.Error(err)
		} else if err == nil {
			defer f.Close()

			r.W.Header().Set("Content-Type", "text/javascript")
			io.Copy(r.W, f)

			return nil
		}
	}

	return app.Errorf("file not found: %s", name)
}
Пример #4
0
func GenerateDeps(dest string) ([]*domain.Source, []string, error) {
	log.Println("Scanning deps...")

	conf := config.Current()

	depstree, err := scan.NewDepsTree(dest)
	if err != nil {
		return nil, nil, err
	}

	namespaces := []string{}
	if conf.Js != nil {
		for _, input := range conf.Js.Inputs {
			if dest != "input" && strings.Contains(input.File, "_test") {
				continue
			}

			file := filepath.Join(conf.Js.Root, input.File)
			ns, err := depstree.GetProvides(file)
			if err != nil {
				return nil, nil, err
			}
			namespaces = append(namespaces, ns...)
		}
	}

	if len(namespaces) == 0 {
		return nil, nil, app.Errorf("no namespaces provided in the input files")
	}

	if dest == "input" {
		// Add the necesary namespaces for the multi-test runner
		namespaces = append(namespaces, "goog.style")
		namespaces = append(namespaces, "goog.userAgent.product")
		namespaces = append(namespaces, "goog.testing.MultiTestRunner")
		namespaces = append(namespaces, depstree.GetTestingNamespaces()...)
	} else if dest == "input-production" {
		namespaces = append(namespaces, "goog.style")
	}

	deps, err := depstree.GetDependencies(namespaces)
	if err != nil {
		return nil, nil, err
	}

	f, err := os.Create(filepath.Join(conf.Build, config.DEPS_NAME))
	if err != nil {
		return nil, nil, app.Error(err)
	}
	defer f.Close()

	if err := scan.WriteDeps(f, deps); err != nil {
		return nil, nil, err
	}

	log.Println("Done scanning deps!")

	return deps, namespaces, nil
}
Пример #5
0
func RawOutput(r *app.Request) error {
	if err := hooks.PreCompile(); err != nil {
		return err
	}

	if err := gss.Compile(); err != nil {
		return err
	}

	if err := soy.Compile(); err != nil {
		return err
	}

	_, namespaces, err := js.GenerateDeps("input-production")
	if err != nil {
		return err
	}

	log.Println("Output RAW mode")

	conf := config.Current()
	content := bytes.NewBuffer(nil)

	base := path.Join(conf.Library.Root, "closure", "goog", "base.js")
	if err := addFile(content, base); err != nil {
		return err
	}

	if err := addFile(content, path.Join(conf.Build, config.RENAMING_MAP_NAME)); err != nil {
		return err
	}

	if err := addFile(content, path.Join(conf.Build, config.DEPS_NAME)); err != nil {
		return err
	}

	if err := hooks.PostCompile(); err != nil {
		return err
	}

	css := make([]byte, 0)
	if conf.Gss != nil {
		css, err = ioutil.ReadFile(filepath.Join(conf.Build, config.CSS_NAME))
		if err != nil {
			return app.Error(err)
		}
	}

	data := map[string]interface{}{
		"Content":    template.HTML(string(content.Bytes())),
		"Port":       config.Port,
		"LT":         template.HTML("<"),
		"Namespaces": template.HTML("'" + strings.Join(namespaces, "', '") + "'"),
		"Css":        template.HTML(template.JSEscapeString(string(css))),
	}
	r.W.Header().Set("Content-Type", "text/javascript")
	return r.ExecuteTemplate([]string{"raw"}, data)
}
Пример #6
0
func calcFileSha1(filename string) (string, error) {
	cmd := exec.Command("sha1sum", filename)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", app.Error(err)
	}

	return strings.Split(string(output), " ")[0], nil
}
Пример #7
0
func copyFile(from, to string) error {
	src, err := os.Open(from)
	if err != nil {
		return app.Error(err)
	}
	defer src.Close()

	dest, err := os.Create(to)
	if err != nil {
		return app.Error(err)
	}
	defer dest.Close()

	if _, err = io.Copy(dest, src); err != nil {
		return app.Error(err)
	}

	return nil
}
Пример #8
0
func outputMap() error {
	conf := config.Current()
	if conf.Map == nil {
		return nil
	}

	f, err := os.Create(conf.Map.File)
	if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	fmt.Fprintf(f, "var mapping = ")
	if err := json.NewEncoder(f).Encode(&mapping); err != nil {
		return app.Error(err)
	}

	return nil
}
Пример #9
0
func CompiledJs(r *app.Request) error {
	r.W.Header().Set("Content-Type", "text/javascript")
	conf := config.Current()

	if err := FullCompile(); err != nil {
		return err
	}

	f, err := os.Open(path.Join(conf.Build, config.JS_NAME))
	if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	if _, err := io.Copy(r.W, f); err != nil {
		return app.Error(err)
	}

	return nil
}
Пример #10
0
func addFile(w io.Writer, name string) error {
	f, err := os.Open(name)
	if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	io.Copy(w, f)

	return nil
}
Пример #11
0
// Save the caches to a file.
func Dump() error {
	conf := config.Current()

	f, err := os.Create(filepath.Join(conf.Build, CACHE_FILENAME))
	if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	log.Println("Write", len(modificationCache), "modifications and", len(dataCache), "datas!")

	e := gob.NewEncoder(f)
	if err := e.Encode(&modificationCache); err != nil {
		return app.Error(err)
	}
	if err := e.Encode(&dataCache); err != nil {
		return app.Error(err)
	}

	return nil
}
Пример #12
0
func cleanRenamingMap() error {
	conf := config.Current()

	// Create/Clean the renaming map file to avoid compilation errors (the JS
	// compiler assumes there's a file with this name there).
	f, err := os.Create(path.Join(conf.Build, config.RENAMING_MAP_NAME))
	if err != nil {
		return app.Error(err)
	}
	f.Close()

	return nil
}
Пример #13
0
func Load() error {
	if globalConf != nil && !NoCache {
		info, err := os.Lstat(ConfPath)
		if err != nil {
			return app.Error(err)
		}

		if info.ModTime() == lastModification {
			return nil
		}
	}

	f, err := os.Open(ConfPath)
	if err != nil {
		return app.Error(err)
	}
	defer f.Close()

	conf := new(Config)
	if err := xml.NewDecoder(f).Decode(&conf); err != nil {
		return app.Error(err)
	}

	// Assign it before validating, because we need it to
	// inherit targets.
	globalConf = conf

	if err := conf.validate(); err != nil {
		return err
	}

	info, err := os.Lstat(ConfPath)
	if err != nil {
		return app.Error(err)
	}
	lastModification = info.ModTime()

	return nil
}
Пример #14
0
// Called before each compilation task. It load the caches
// and reload the confs if needed.
func PreCompile() error {
	if err := config.Load(); err != nil {
		return err
	}

	conf := config.Current()
	if err := os.MkdirAll(conf.Build, 0755); err != nil {
		return app.Error(err)
	}

	var err error
	loadCacheOnce.Do(func() {
		err = cache.Load()
	})

	return err
}
Пример #15
0
// Search for "_test.js" files and relativize them to
// the root directory. It replaces the .js ext with .html.
func scanTests() ([]string, error) {
	conf := config.Current()

	tests, err := scan.Do(conf.Js.Root, "_test.js")
	if err != nil {
		return nil, err
	}

	for i, test := range tests {
		// Relativize the path adding .html instead of .js
		p, err := filepath.Rel(conf.Js.Root, test[:len(test)-2]+"html")
		if err != nil {
			return nil, app.Error(err)
		}
		tests[i] = p
	}

	return tests, nil
}
Пример #16
0
// Checks if filename has been modified since the last time
// it was scanned. It so, or if it's not present in the cache,
// it returns true and stores the new time.
func Modified(dest, filename string) (bool, error) {
	if config.NoCache {
		return true, nil
	}

	name := dest + filename

	info, err := os.Lstat(filename)
	if err != nil {
		return false, app.Error(err)
	}

	modified, ok := modificationCache[name]

	if !ok || info.ModTime() != modified {
		modificationCache[name] = info.ModTime()
		return true, nil
	}

	return false, nil
}
Пример #17
0
func (v *visitor) scan(file string, ext string) error {
	ls, err := ioutil.ReadDir(file)
	if err != nil {
		return app.Error(err)
	}

	for _, entry := range ls {
		fullpath := filepath.Join(file, entry.Name())

		if entry.IsDir() {
			if v.validDir(fullpath, entry.Name()) {
				if err := v.scan(fullpath, ext); err != nil {
					return err
				}
			}
		} else if strings.HasSuffix(entry.Name(), ext) {
			v.results = append(v.results, fullpath)
		}
	}

	return nil
}
Пример #18
0
// Compile all modified templates
func Compile() error {
	conf := config.Current()

	if conf.Soy == nil || conf.Soy.Root == "" {
		return nil
	}

	if err := os.MkdirAll(path.Join(conf.Build, "templates"), 0755); err != nil {
		return app.Error(err)
	}

	buildPrefix := filepath.Join(conf.Build, "templates")
	oldSoy, err := scan.Do(buildPrefix, ".js")
	if err != nil {
		return err
	}

	soy, err := scan.Do(conf.Soy.Root, ".soy")
	if err != nil {
		return err
	}

	indexed := map[string]bool{}
	for _, f := range soy {
		f = f[len(conf.Soy.Root):]
		indexed[f] = true
	}

	// Delete compiled templates no longer present in the sources
	for _, f := range oldSoy {
		compare := f[len(buildPrefix) : len(f)-3]
		if _, ok := indexed[compare]; !ok {
			if err := os.Remove(f); err != nil {
				return app.Error(err)
			}
		}
	}

	if len(soy) == 0 {
		return nil
	}

	for _, t := range soy {
		if modified, err := cache.Modified("compile", t); err != nil {
			return err
		} else if !modified {
			continue
		}

		prel, err := filepath.Rel(conf.Soy.Root, t)
		if err != nil {
			return app.Error(err)
		}

		out := path.Join(conf.Build, "templates", prel+".js")
		if err := os.MkdirAll(path.Dir(out), 0755); err != nil {
			return app.Error(err)
		}

		log.Println("Compiling template", t, "...")

		// Run the compiler command
		cmd := exec.Command(
			"java",
			"-jar", path.Join(conf.Soy.Compiler, "build", "SoyToJsSrcCompiler.jar"),
			"--outputPathFormat", out,
			"--shouldGenerateJsdoc",
			"--shouldProvideRequireSoyNamespaces",
			"--cssHandlingScheme", "goog",
			t)

		output, err := cmd.CombinedOutput()
		if err != nil {
			return app.Errorf("exec error with %s: %s\n%s", t, err, string(output))
		}

		log.Println("Done compiling template!")
	}

	return nil
}
Пример #19
0
// Creates a new source. Returns the source, if it has been
// loaded from cache or not, and an error.
func NewSource(dest, filename, base string) (*Source, bool, error) {
	src := cache.ReadData(dest+filename, new(Source)).(*Source)

	// Return the file from cache if possible
	if modified, err := cache.Modified(dest, filename); err != nil {
		return nil, false, err
	} else if !modified {
		return src, true, nil
	}

	// Reset the source info
	src.Provides = []string{}
	src.Requires = []string{}
	src.Base = (filename == base)
	src.Filename = filename

	// Open the file
	f, err := os.Open(filename)
	if err != nil {
		return nil, false, app.Error(err)
	}
	defer f.Close()

	r := bufio.NewReader(f)
	for {
		// Read it line by line
		line, _, err := r.ReadLine()
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, false, err
		}

		// Find the goog.provide() calls
		if strings.Contains(string(line), "goog.provide") {
			matchs := provideRe.FindSubmatch(line)
			if matchs != nil {
				src.Provides = append(src.Provides, string(matchs[1]))
				continue
			}
		}

		// Find the goog.require() calls
		if strings.Contains(string(line), "goog.require") {
			matchs := requiresRe.FindSubmatch(line)
			if matchs != nil {
				src.Requires = append(src.Requires, string(matchs[1]))
				continue
			}
		}
	}

	// Validates the base file
	if src.Base {
		if len(src.Provides) > 0 || len(src.Requires) > 0 {
			return nil, false,
				app.Errorf("base files should not provide or require namespaces: %s", filename)
		}
		src.Provides = append(src.Provides, "goog")
	}

	return src, false, nil
}