mirror of https://github.com/perkeep/perkeep.git
misc/genjsdeps: command to generate closure deps
reusing code from pkg/server/ui.go Change-Id: I56b8d4b42df2fbcbbe3d654261036cdb907f9f27
This commit is contained in:
parent
cbea6a6692
commit
89e14d8f7d
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Copyright 2013 The Camlistore Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// The genjsdeps command, similarly to the closure depswriter.py tool,
|
||||
// outputs to os.Stdout for each .js file, which namespaces
|
||||
// it provides, and the namespaces it requires, hence allowing
|
||||
// the closure library to resolve dependencies between those files.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO(mpl): make a library and a separate command which uses
|
||||
// that library.
|
||||
// http://camlistore.org/issue/142
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: genjsdeps <dir>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(args) != 1 {
|
||||
usage()
|
||||
}
|
||||
dir := path.Clean(args[0])
|
||||
fi, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
log.Fatalf("%v not a dir", dir)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.HasSuffix(path, ".js") {
|
||||
return nil
|
||||
}
|
||||
suffix := path[len(dir)+1:]
|
||||
prov, req, err := parseProvidesRequires(info, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(prov) > 0 {
|
||||
fmt.Fprintf(&buf, "goog.addDependency(%q, %v, %v);\n", "../../"+suffix, jsList(prov), jsList(req))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Error walking %d generating deps.js: %v", dir, err)
|
||||
}
|
||||
io.Copy(os.Stdout, &buf)
|
||||
}
|
||||
|
||||
var provReqRx = regexp.MustCompile(`^goog\.(provide|require)\(['"]([\w\.]+)['"]\)`)
|
||||
|
||||
type depCacheItem struct {
|
||||
modTime time.Time
|
||||
provides, requires []string
|
||||
}
|
||||
|
||||
var (
|
||||
depCacheMu sync.Mutex
|
||||
depCache = map[string]depCacheItem{}
|
||||
)
|
||||
|
||||
func parseProvidesRequires(fi os.FileInfo, path string) (provides, requires []string, err error) {
|
||||
mt := fi.ModTime()
|
||||
depCacheMu.Lock()
|
||||
defer depCacheMu.Unlock()
|
||||
if ci := depCache[path]; ci.modTime.Equal(mt) {
|
||||
return ci.provides, ci.requires, nil
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
br := bufio.NewReader(f)
|
||||
for {
|
||||
l, err := br.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !strings.HasPrefix(l, "goog.") {
|
||||
continue
|
||||
}
|
||||
m := provReqRx.FindStringSubmatch(l)
|
||||
if m != nil {
|
||||
if m[1] == "provide" {
|
||||
provides = append(provides, m[2])
|
||||
} else {
|
||||
requires = append(requires, m[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
depCache[path] = depCacheItem{provides: provides, requires: requires, modTime: mt}
|
||||
return provides, requires, nil
|
||||
}
|
||||
|
||||
// jsList prints a list of strings as JavaScript list.
|
||||
type jsList []string
|
||||
|
||||
func (s jsList) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('[')
|
||||
for i, v := range s {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(&buf, "%q", v)
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.String()
|
||||
}
|
Loading…
Reference in New Issue