use_find_cache: add another pattern
in repo/android/build/core/base_rules.mk
java_resource_file_groups+= ...
cd ${TOP_DIR}${LOCAL_PATH}/${dir} && find . -type d -a -name ".svn" -prune \
-o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! \
-name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" \
-a \! -name "*~" -print )
refactor androidFindCache. add walk method.
% time ./repo/android.sh kati -c > /dev/null
find: `dummy': No such file or directory
find: `dummy': No such file or directory
fatal: Not a git repository: 'packages/apps/Camera2/.git'
./repo/android.sh kati -c > /dev/null 32.38s user 41.67s system 130% cpu 56.897 total
% time ./repo/android.sh kati -c -use_find_cache > /dev/null
fatal: Not a git repository: 'packages/apps/Camera2/.git'
./repo/android.sh kati -c -use_find_cache > /dev/null 33.26s user 18.88s system 153% cpu 33.974 total
diff --git a/func.go b/func.go
index 93f9f31..6484ead 100644
--- a/func.go
+++ b/func.go
@@ -765,10 +765,19 @@
roots: roots,
}
}
+ if dir, ok := matchAndroidFindJavaResourceFileGroup(expr); ok {
+ androidFindCache.init()
+ return &funcShellAndroidFindJavaResourceFileGroup{
+ funcShell: f,
+ dir: dir,
+ }
+ }
+ Logf("shell compact no match: %s", expr)
return f
}
-// pattern:
+// pattern in repo/android/build/core/definitions.mk
+// find-subdir-assets
// if [ -d $1 ] ; then cd $1 ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi
func matchAndroidFindFileInDir(expr Expr) (Value, bool) {
// literal: "if [ -d "
@@ -822,7 +831,8 @@
androidFindCache.findInDir(&sw, dir)
}
-// pattern:
+// pattern in repo/android/build/core/definitions.mk
+// all-java-files-under
// cd ${LOCAL_PATH} ; find -L $1 -name "*.java" -and -not -name ".*"
func matchAndroidFindJavaInDir(expr Expr) (Value, Value, bool) {
// literal: "cd "
@@ -897,12 +907,70 @@
freeBuf(buf)
}
-// TODO(ukai): pattern:
-//
+// pattern: in repo/android/build/core/base_rules.mk
+// java_resource_file_groups+= ...
// cd ${TOP_DIR}${LOCAL_PATH}/${dir} && find . -type d -a -name ".svn" -prune \
// -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! \
// -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" \
// -a \! -name "*~" -print )
+func matchAndroidFindJavaResourceFileGroup(expr Expr) (Value, bool) {
+ // literal: "cd "
+ // varref: TOP_DIR
+ // varref: LOCAL_PATH
+ // literal: "/"
+ // varref: dir
+ // literal: " && find . -type d -a name ".svn" -prune -o .."
+ if len(expr) != 6 {
+ return nil, false
+ }
+ if expr[0] != literal("cd ") {
+ return nil, false
+ }
+ if _, ok := expr[1].(varref); !ok {
+ return nil, false
+ }
+ if _, ok := expr[2].(varref); !ok {
+ return nil, false
+ }
+ if expr[3] != literal("/") {
+ return nil, false
+ }
+ if _, ok := expr[4].(varref); !ok {
+ return nil, false
+ }
+ if expr[5] != literal(` && find . -type d -a -name ".svn" -prune -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" -a \! -name "*~" -print `) {
+ Logf("shell compact mismatch: expr[5]=%q", expr[5])
+ return nil, false
+ }
+ return expr[1:5], true
+}
+
+type funcShellAndroidFindJavaResourceFileGroup struct {
+ *funcShell
+ dir Value
+}
+
+func (f *funcShellAndroidFindJavaResourceFileGroup) Eval(w io.Writer, ev *Evaluator) {
+ abuf := newBuf()
+ fargs := ev.args(abuf, f.dir)
+ dir := string(trimSpaceBytes(fargs[0]))
+ freeBuf(abuf)
+ Logf("shellAndroidFindJavaResourceFileGroup %s => %s", f.dir.String(), dir)
+ if strings.Contains(dir, "..") {
+ Logf("shellAndroidFindJavaResourceFileGroup contains ..: call original shell")
+ f.funcShell.Eval(w, ev)
+ return
+ }
+ if !androidFindCache.ready() {
+ Logf("shellAndroidFindJavaResourceFileGroup androidFindCache is not ready: call original shell")
+ f.funcShell.Eval(w, ev)
+ return
+ }
+ sw := ssvWriter{w: w}
+ androidFindCache.findJavaResourceFileGroup(&sw, dir)
+}
+
+// TODO(ukai): pattern:
//
// echo $1 | tr 'a-zA-Z' 'n-za-mN-ZA-M'
diff --git a/pathutil.go b/pathutil.go
index 4a9113c..366a890 100644
--- a/pathutil.go
+++ b/pathutil.go
@@ -1,6 +1,8 @@
package main
import (
+ "errors"
+ "fmt"
"os"
"os/exec"
"path/filepath"
@@ -124,74 +126,99 @@
return f[i].path < f[j].path
}
-// if [ -d $1 ] ; then cd $1 ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi
-func (c *androidFindCacheT) findInDir(sw *ssvWriter, dir string) {
- dir = strings.TrimPrefix(dir, "./")
+var errSkipDir = errors.New("skip dir")
+
+func (c *androidFindCacheT) walk(dir string, walkFn func(int, fileInfo) error) error {
i := sort.Search(len(c.files), func(i int) bool {
return c.files[i].path >= dir
})
Logf("android find in dir cache: %s i=%d/%d", dir, i, len(c.files))
- for ; i < len(c.files); i++ {
- if c.files[i].path != dir {
- if !strings.HasPrefix(c.files[i].path, dir) {
- Logf("android find in dir cache: %s different prefix at %d: %s", dir, i, c.files[i].path)
- break
+ start := i
+ var skipdirs []string
+Loop:
+ for i := start; i < len(c.files); i++ {
+ if c.files[i].path == dir {
+ err := walkFn(i, c.files[i])
+ if err != nil {
+ return err
}
- if !strings.HasPrefix(c.files[i].path, dir+"/") {
- continue
+ continue
+ }
+ if !strings.HasPrefix(c.files[i].path, dir) {
+ Logf("android find in dir cache: %s end=%d/%d", dir, i, len(c.files))
+ return nil
+ }
+ if !strings.HasPrefix(c.files[i].path, dir+"/") {
+ continue
+ }
+ for _, skip := range skipdirs {
+ if strings.HasPrefix(c.files[i].path, skip+"/") {
+ continue Loop
}
}
- // -not -name '.*'
- if strings.HasPrefix(filepath.Base(c.files[i].path), ".") {
+
+ err := walkFn(i, c.files[i])
+ if err == errSkipDir {
+ Logf("android find in skip dir: %s", c.files[i].path)
+ skipdirs = append(skipdirs, c.files[i].path)
continue
}
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// pattern in repo/android/build/core/definitions.mk
+// find-subdir-assets
+// if [ -d $1 ] ; then cd $1 ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi
+func (c *androidFindCacheT) findInDir(sw *ssvWriter, dir string) {
+ dir = filepath.Clean(dir)
+ Logf("android find in dir cache: %s", dir)
+ c.walk(dir, func(_ int, fi fileInfo) error {
+ // -not -name '.*'
+ if strings.HasPrefix(filepath.Base(fi.path), ".") {
+ return nil
+ }
// -type f and -not -type l
// regular type and not symlink
- if !c.files[i].mode.IsRegular() {
- continue
+ if !fi.mode.IsRegular() {
+ return nil
}
- name := strings.TrimPrefix(c.files[i].path, dir+"/")
+ name := strings.TrimPrefix(fi.path, dir+"/")
name = "./" + name
sw.WriteString(name)
Logf("android find in dir cache: %s=> %s", dir, name)
- }
+ return nil
+ })
}
+// pattern in repo/android/build/core/definitions.mk
+// all-java-files-under
// cd ${LOCAL_PATH} ; find -L $1 -name "*.java" -and -not -name ".*"
// returns false if symlink is found.
func (c *androidFindCacheT) findJavaInDir(sw *ssvWriter, chdir string, root string) bool {
- chdir = strings.TrimPrefix(chdir, "./")
+ chdir = filepath.Clean(chdir)
dir := filepath.Join(chdir, root)
- i := sort.Search(len(c.files), func(i int) bool {
- return c.files[i].path >= dir
- })
- Logf("android find java in dir cache: %s i=%d/%d", dir, i, len(c.files))
- start := i
- end := len(c.files)
+ Logf("android find java in dir cache: %s %s", chdir, root)
// check symlinks
- for ; i < len(c.files); i++ {
- if c.files[i].path != dir {
- if !strings.HasPrefix(c.files[i].path, dir) {
- Logf("android find in dir cache: %s different prefix at %d: %s", dir, i, c.files[i].path)
- end = i
- break
- }
- if !strings.HasPrefix(c.files[i].path, dir+"/") {
- continue
- }
- }
- if c.files[i].mode&os.ModeSymlink == os.ModeSymlink {
+ var matches []int
+ err := c.walk(dir, func(i int, fi fileInfo) error {
+ if fi.mode&os.ModeSymlink == os.ModeSymlink {
Logf("android find java in dir cache: detect symlink %s %v", c.files[i].path, c.files[i].mode)
- return false
+ return fmt.Errorf("symlink %s", fi.path)
}
+ matches = append(matches, i)
+ return nil
+ })
+ if err != nil {
+ return false
}
-
// no symlinks
- for i := start; i < end; i++ {
- if c.files[i].path != dir && !strings.HasPrefix(c.files[i].path, dir+"/") {
- continue
- }
- base := filepath.Base(c.files[i].path)
+ for _, i := range matches {
+ fi := c.files[i]
+ base := filepath.Base(fi.path)
// -name "*.java"
if filepath.Ext(base) != ".java" {
continue
@@ -200,9 +227,46 @@
if strings.HasPrefix(base, ".") {
continue
}
- name := strings.TrimPrefix(c.files[i].path, chdir+"/")
+ name := strings.TrimPrefix(fi.path, chdir+"/")
sw.WriteString(name)
Logf("android find java in dir cache: %s=> %s", dir, name)
}
return true
}
+
+// pattern: in repo/android/build/core/base_rules.mk
+// java_resource_file_groups+= ...
+// cd ${TOP_DIR}${LOCAL_PATH}/${dir} && find . -type d -a -name ".svn" -prune \
+// -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! \
+// -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" \
+// -a \! -name "*~" -print )
+func (c *androidFindCacheT) findJavaResourceFileGroup(sw *ssvWriter, dir string) {
+ Logf("android find java resource in dir cache: %s", dir)
+ c.walk(filepath.Clean(dir), func(_ int, fi fileInfo) error {
+ // -type d -a -name ".svn" -prune
+ if fi.mode.IsDir() && filepath.Base(fi.path) == ".svn" {
+ return errSkipDir
+ }
+ // -type f
+ if !fi.mode.IsRegular() {
+ return nil
+ }
+ // ! -name "*.java" -a ! -name "package.html" -a
+ // ! -name "overview.html" -a ! -name ".*.swp" -a
+ // ! -name ".DS_Store" -a ! -name "*~"
+ base := filepath.Base(fi.path)
+ if filepath.Ext(base) == ".java" ||
+ base == "package.html" ||
+ base == "overview.html" ||
+ (strings.HasPrefix(base, ".") && strings.HasSuffix(base, ".swp")) ||
+ base == ".DS_Store" ||
+ strings.HasSuffix(base, "~") {
+ return nil
+ }
+ name := strings.TrimPrefix(fi.path, dir+"/")
+ name = "./" + name
+ sw.WriteString(name)
+ Logf("android find java resource in dir cache: %s=> %s", dir, name)
+ return nil
+ })
+}