Skip to content

Commit 2b7c90f

Browse files
[wip] Add project cache
1 parent 4f847e5 commit 2b7c90f

File tree

5 files changed

+172
-31
lines changed

5 files changed

+172
-31
lines changed

newt/cache/cache.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package cache
21+
22+
import (
23+
"encoding/gob"
24+
"fmt"
25+
"mynewt.apache.org/newt/newt/interfaces"
26+
"mynewt.apache.org/newt/newt/repo"
27+
"mynewt.apache.org/newt/util"
28+
"os"
29+
"path/filepath"
30+
)
31+
32+
type ProjectCache struct {
33+
baseDir string
34+
}
35+
36+
func InitCache(projDir string) *ProjectCache {
37+
pc := ProjectCache{}
38+
pc.baseDir = filepath.Join(projDir, ".cache")
39+
40+
if _, err := os.Stat(pc.baseDir); os.IsNotExist(err) {
41+
if err := os.Mkdir(pc.baseDir, 0754); err != nil {
42+
return nil
43+
}
44+
}
45+
46+
return &pc
47+
}
48+
49+
func (pc *ProjectCache) getPackagesFile(repo *repo.Repo) string {
50+
return fmt.Sprintf(filepath.Join(pc.baseDir, repo.Name()))
51+
}
52+
53+
func (pc *ProjectCache) AddPackages(repo *repo.Repo, pkgMap map[string]interfaces.PackageInterface) {
54+
cacheName := pc.getPackagesFile(repo)
55+
var dirList []string
56+
57+
for _, v := range pkgMap {
58+
dirList = append(dirList, v.BasePath())
59+
}
60+
61+
f, err := os.Create(cacheName)
62+
if err != nil {
63+
util.OneTimeWarning("Failed to create cache file for \"%s\"", repo.Name())
64+
return
65+
}
66+
67+
defer f.Close()
68+
69+
enc := gob.NewEncoder(f)
70+
err = enc.Encode(dirList)
71+
if err != nil {
72+
util.OneTimeWarning("Failed to update cache file for \"%s\"", repo.Name())
73+
}
74+
}
75+
76+
func (pc *ProjectCache) GetPackagesDirs(repo *repo.Repo) []string {
77+
cacheName := pc.getPackagesFile(repo)
78+
var dirList []string
79+
80+
f, err := os.Open(cacheName)
81+
if err != nil {
82+
util.OneTimeWarning("Failed to open cache file for \"%s\"", repo.Name())
83+
return nil
84+
}
85+
86+
defer f.Close()
87+
88+
enc := gob.NewDecoder(f)
89+
err = enc.Decode(&dirList)
90+
if err != nil {
91+
util.OneTimeWarning("Failed to read cache for \"%s\"", repo.Name())
92+
return nil
93+
}
94+
95+
return dirList
96+
}

newt/pkg/localpackage.go

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,34 @@ func LocalPackageSpecialName(dirName string) bool {
449449
return ok
450450
}
451451

452+
func ReadPackage(repo *repo.Repo, pkgMap map[string]interfaces.PackageInterface,
453+
pkgPath string) ([]string, error) {
454+
455+
var warnings []string
456+
457+
pkg, err := LoadLocalPackage(repo, pkgPath)
458+
if err != nil {
459+
warnings = append(warnings, err.Error())
460+
return warnings, nil
461+
}
462+
463+
if oldPkg, ok := pkgMap[pkg.Name()]; ok {
464+
oldlPkg := oldPkg.(*LocalPackage)
465+
warnings = append(warnings,
466+
fmt.Sprintf("Multiple packages with same pkg.name=%s "+
467+
"in repo %s; path1=%s path2=%s", oldlPkg.Name(), repo.Name(),
468+
oldlPkg.BasePath(), pkg.BasePath()))
469+
470+
return warnings, nil
471+
}
472+
473+
pkgMap[pkg.Name()] = pkg
474+
475+
return warnings, nil
476+
}
477+
452478
func ReadLocalPackageRecursive(repo *repo.Repo,
453-
pkgList map[string]interfaces.PackageInterface, basePath string,
479+
pkgMap map[string]interfaces.PackageInterface, basePath string,
454480
pkgName string, searchedMap map[string]struct{}) ([]string, error) {
455481

456482
var warnings []string
@@ -465,7 +491,7 @@ func ReadLocalPackageRecursive(repo *repo.Repo,
465491
continue
466492
}
467493

468-
subWarnings, err := ReadLocalPackageRecursive(repo, pkgList,
494+
subWarnings, err := ReadLocalPackageRecursive(repo, pkgMap,
469495
basePath, filepath.Join(pkgName, name), searchedMap)
470496
warnings = append(warnings, subWarnings...)
471497
if err != nil {
@@ -477,39 +503,21 @@ func ReadLocalPackageRecursive(repo *repo.Repo,
477503
return warnings, nil
478504
}
479505

480-
pkg, err := LoadLocalPackage(repo, filepath.Join(basePath, pkgName))
481-
if err != nil {
482-
warnings = append(warnings, err.Error())
483-
return warnings, nil
484-
}
506+
var subWarnings []string
507+
subWarnings, err = ReadPackage(repo, pkgMap, filepath.Join(basePath, pkgName))
508+
warnings = append(warnings, subWarnings...)
485509

486-
if oldPkg, ok := pkgList[pkg.Name()]; ok {
487-
oldlPkg := oldPkg.(*LocalPackage)
488-
warnings = append(warnings,
489-
fmt.Sprintf("Multiple packages with same pkg.name=%s "+
490-
"in repo %s; path1=%s path2=%s", oldlPkg.Name(), repo.Name(),
491-
oldlPkg.BasePath(), pkg.BasePath()))
492-
493-
return warnings, nil
494-
}
495-
496-
pkgList[pkg.Name()] = pkg
497-
498-
return warnings, nil
510+
return warnings, err
499511
}
500512

501-
func ReadLocalPackages(repo *repo.Repo, basePath string) (
502-
*map[string]interfaces.PackageInterface, []string, error) {
503-
504-
pkgMap := &map[string]interfaces.PackageInterface{}
505-
513+
func ReadLocalPackages(repo *repo.Repo, pkgMap map[string]interfaces.PackageInterface, basePath string) ([]string, error) {
506514
// Keep track of which directories we have traversed. Prevent infinite
507515
// loops caused by symlink cycles by not inspecting the same directory
508516
// twice.
509517
searchedMap := map[string]struct{}{}
510518

511-
warnings, err := ReadLocalPackageRecursive(repo, *pkgMap,
519+
warnings, err := ReadLocalPackageRecursive(repo, pkgMap,
512520
basePath, "", searchedMap)
513521

514-
return pkgMap, warnings, err
522+
return warnings, err
515523
}

newt/project/project.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package project
2121

2222
import (
2323
"fmt"
24+
"mynewt.apache.org/newt/newt/cache"
2425
"os"
2526
"path"
2627
"path/filepath"
@@ -57,6 +58,8 @@ type Project struct {
5758
// Base path of the project
5859
BasePath string
5960

61+
cache *cache.ProjectCache
62+
6063
packages interfaces.PackageList
6164

6265
// Contains all the repos that form this project. Each repo is in one of
@@ -634,6 +637,13 @@ func (proj *Project) Init(dir string, download bool) error {
634637
return err
635638
}
636639

640+
if util.EnableProjectCache {
641+
proj.cache = cache.InitCache(proj.BasePath)
642+
if proj.cache == nil {
643+
util.OneTimeWarning("Failed to initialize project cache")
644+
}
645+
}
646+
637647
return nil
638648
}
639649

@@ -741,12 +751,37 @@ func (proj *Project) loadPackageList() error {
741751
// packages / store them in the project package list.
742752
repos := proj.Repos()
743753
for name, repo := range repos {
744-
list, warnings, err := pkg.ReadLocalPackages(repo, repo.Path())
745-
if err == nil {
746-
proj.packages[name] = list
754+
pkgMap := &map[string]interfaces.PackageInterface{}
755+
756+
var dirList []string
757+
758+
if proj.cache != nil {
759+
dirList = proj.cache.GetPackagesDirs(repo)
747760
}
748761

749-
proj.warnings = append(proj.warnings, warnings...)
762+
if proj.cache != nil && dirList != nil {
763+
log.Debug("Using cache for packages in \"%s\"\n", repo.Name())
764+
for _, pkgPath := range dirList {
765+
warnings, err := pkg.ReadPackage(repo, *pkgMap, pkgPath)
766+
if err == nil {
767+
proj.packages[name] = pkgMap
768+
}
769+
770+
proj.warnings = append(proj.warnings, warnings...)
771+
}
772+
} else {
773+
log.Debug("Not using cache for packages in \"%s\"\n", repo.Name())
774+
warnings, err := pkg.ReadLocalPackages(repo, *pkgMap, repo.Path())
775+
if err == nil {
776+
proj.packages[name] = pkgMap
777+
}
778+
779+
if proj.cache != nil {
780+
proj.cache.AddPackages(repo, *pkgMap)
781+
}
782+
783+
proj.warnings = append(proj.warnings, warnings...)
784+
}
750785
}
751786

752787
return nil

newt/settings/settings.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func processNewtrc(yc ycfg.YCfg) {
5959

6060
util.SkipNewtCompat, _ = yc.GetValBoolDflt("skip_newt_compat", nil, false)
6161
util.SkipSyscfgRepoHash, _ = yc.GetValBoolDflt("skip_syscfg_repo_hash", nil, false)
62+
util.EnableProjectCache, _ = yc.GetValBoolDflt("project_cache", nil, false)
6263
}
6364

6465
func readNewtrc() ycfg.YCfg {

util/util.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var ShallowCloneDepth int
5151
var logFile *os.File
5252
var SkipNewtCompat bool
5353
var SkipSyscfgRepoHash bool
54+
var EnableProjectCache bool
5455

5556
func ParseEqualsPair(v string) (string, string, error) {
5657
s := strings.Split(v, "=")

0 commit comments

Comments
 (0)