зеркало из https://github.com/mozilla/scribe.git
initial import chains implementation
This commit is contained in:
Родитель
36d040c3cb
Коммит
f8914dce49
|
@ -0,0 +1,19 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Contributor:
|
||||
// - Aaron Meihm ameihm@mozilla.com
|
||||
|
||||
package scribe
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func hasChainVariables(arg string) bool {
|
||||
if strings.Contains(arg, "${chain_root}") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -48,6 +48,11 @@ func (d *Document) GetTestIdentifiers() []string {
|
|||
}
|
||||
|
||||
func (d *Document) prepareObjects() error {
|
||||
// Mark any chain objects; these will be skipped during preparation
|
||||
// as they are dependant on evaluation of the root object.
|
||||
for i := range d.Objects {
|
||||
d.Objects[i].markChain()
|
||||
}
|
||||
// Note that prepare() will return an error if something goes wrong
|
||||
// but we don't propagate this back. Errors within object preparation
|
||||
// are kept localized to the object, and are not considered fatal to
|
||||
|
@ -55,6 +60,10 @@ func (d *Document) prepareObjects() error {
|
|||
for i := range d.Objects {
|
||||
d.Objects[i].prepare(d)
|
||||
}
|
||||
debugPrint("prepareObjects(): firing any import chains\n")
|
||||
for i := range d.Objects {
|
||||
d.Objects[i].fireChains(d)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
@ -23,6 +24,8 @@ type filecontent struct {
|
|||
Expression string `json:"expression"`
|
||||
Concat string `json:"concat"`
|
||||
|
||||
ImportChain []string `json:"import-chain"`
|
||||
|
||||
matches []contentMatch
|
||||
}
|
||||
|
||||
|
@ -57,6 +60,46 @@ func (f *filecontent) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *filecontent) fireChains(d *Document) []evaluationCriteria {
|
||||
if len(f.ImportChain) == 0 {
|
||||
return nil
|
||||
}
|
||||
debugPrint("fireChains(): firing chains for filecontent object\n")
|
||||
uids := make([]string, 0)
|
||||
for _, x := range f.matches {
|
||||
found := false
|
||||
for _, y := range uids {
|
||||
if x.path == y {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
uids = append(uids, x.path)
|
||||
}
|
||||
for _, x := range uids {
|
||||
varlist := make([]variable, 0)
|
||||
debugPrint("fireChains(): run for \"%v\"\n", x)
|
||||
|
||||
d, _ := path.Split(x)
|
||||
newvar := variable{Key: "chain_root", Value: d}
|
||||
varlist = append(varlist, newvar)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *filecontent) mergeCriteria(c []evaluationCriteria) {
|
||||
}
|
||||
|
||||
func (f *filecontent) isChain() bool {
|
||||
if hasChainVariables(f.Path) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *filecontent) isModifier() bool {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -29,6 +29,17 @@ func (f *filename) isModifier() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (f *filename) isChain() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *filename) fireChains(d *Document) []evaluationCriteria {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *filename) mergeCriteria(c []evaluationCriteria) {
|
||||
}
|
||||
|
||||
func (f *filename) validate() error {
|
||||
if len(f.Path) == 0 {
|
||||
return fmt.Errorf("filename path must be set")
|
||||
|
|
|
@ -18,6 +18,7 @@ type object struct {
|
|||
Package pkg `json:"package"`
|
||||
Raw raw `json:"raw"`
|
||||
|
||||
isChain bool // True if object is part of an import chain.
|
||||
prepared bool // True if object has been prepared.
|
||||
err error // The last error condition encountered during preparation.
|
||||
}
|
||||
|
@ -25,8 +26,11 @@ type object struct {
|
|||
type genericSource interface {
|
||||
prepare() error
|
||||
getCriteria() []evaluationCriteria
|
||||
isChain() bool
|
||||
expandVariables([]variable)
|
||||
validate() error
|
||||
mergeCriteria([]evaluationCriteria)
|
||||
fireChains(*Document) []evaluationCriteria
|
||||
}
|
||||
|
||||
func (o *object) validate(d *Document) error {
|
||||
|
@ -44,6 +48,10 @@ func (o *object) validate(d *Document) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *object) markChain() {
|
||||
o.isChain = o.getSourceInterface().isChain()
|
||||
}
|
||||
|
||||
func (o *object) getSourceInterface() genericSource {
|
||||
if o.Package.Name != "" {
|
||||
return &o.Package
|
||||
|
@ -57,7 +65,16 @@ func (o *object) getSourceInterface() genericSource {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *object) fireChains(d *Document) {
|
||||
si := o.getSourceInterface()
|
||||
si.mergeCriteria(si.fireChains(d))
|
||||
}
|
||||
|
||||
func (o *object) prepare(d *Document) error {
|
||||
if o.isChain {
|
||||
debugPrint("prepare(): skipping chain object \"%v\"\n", o.Object)
|
||||
return nil
|
||||
}
|
||||
if o.prepared {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ func (p *pkg) isModifier() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (p *pkg) isChain() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *pkg) validate() error {
|
||||
if len(p.Name) == 0 {
|
||||
return fmt.Errorf("package must specify name")
|
||||
|
@ -32,6 +36,13 @@ func (p *pkg) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *pkg) fireChains(d *Document) []evaluationCriteria {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pkg) mergeCriteria(c []evaluationCriteria) {
|
||||
}
|
||||
|
||||
func (p *pkg) getCriteria() (ret []evaluationCriteria) {
|
||||
for _, x := range p.pkgInfo {
|
||||
n := evaluationCriteria{}
|
||||
|
|
|
@ -24,6 +24,17 @@ func (r *raw) isModifier() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (r *raw) isChain() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *raw) fireChains(d *Document) []evaluationCriteria {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *raw) mergeCriteria(c []evaluationCriteria) {
|
||||
}
|
||||
|
||||
func (r *raw) validate() error {
|
||||
if len(r.Identifiers) == 0 {
|
||||
return fmt.Errorf("at least one identifier must be present")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
TESTDIRS = filecontent filename package concat raw evrtest
|
||||
TESTDIRS = filecontent filename package concat raw import-chain evrtest
|
||||
|
||||
all:
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
var = (1, 5)
|
|
@ -0,0 +1,13 @@
|
|||
all:
|
||||
|
||||
runtests: test.json
|
||||
ifndef SCRIBECMD
|
||||
$(error SCRIBECMD is undefined, tests must be ran from the root of the repository)
|
||||
endif
|
||||
$(SCRIBECMD) -e -f test.json; \
|
||||
|
||||
test.json: test-template.json
|
||||
cat test-template.json | sed 's,REPLACE_IN_MAKEFILE,$(shell pwd),' > test.json
|
||||
|
||||
clean:
|
||||
rm -f test.json
|
|
@ -0,0 +1 @@
|
|||
var = (1, 5)
|
|
@ -0,0 +1 @@
|
|||
var = (1, 5)
|
|
@ -0,0 +1 @@
|
|||
minor = 8
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"variables": [
|
||||
{ "key": "root", "value": "REPLACE_IN_MAKEFILE" }
|
||||
],
|
||||
|
||||
"objects": [
|
||||
{
|
||||
"object": "testfile0-combined",
|
||||
"filecontent": {
|
||||
"path": "${root}",
|
||||
"file": "testfile0",
|
||||
"expression": "var = \\((\\S+), (\\S+)\\)",
|
||||
"concat": ".",
|
||||
"import-chain": [ "testfile1-minor" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"object": "testfile1-minor",
|
||||
"filecontent": {
|
||||
"path": "${chain_root}",
|
||||
"file": "testfile1",
|
||||
"expression": "minor = (\\S+)"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"tests": [
|
||||
{
|
||||
"test": "testfile0-noop",
|
||||
"expectedresult": true,
|
||||
"object": "testfile0-combined"
|
||||
}
|
||||
]
|
||||
}
|
Загрузка…
Ссылка в новой задаче