From f8914dce49a2d2f501e1c3b303b622a88eca714d Mon Sep 17 00:00:00 2001 From: Aaron Meihm Date: Mon, 3 Aug 2015 13:45:11 -0500 Subject: [PATCH] initial import chains implementation --- src/scribe/chain.go | 19 ++++++++++++ src/scribe/document.go | 9 ++++++ src/scribe/filecontent.go | 43 +++++++++++++++++++++++++++ src/scribe/filename.go | 11 +++++++ src/scribe/object.go | 17 +++++++++++ src/scribe/package.go | 11 +++++++ src/scribe/raw.go | 11 +++++++ test/Makefile | 2 +- test/concat/data/dir0/testfile0 | 1 + test/import-chain/Makefile | 13 ++++++++ test/import-chain/data/dir0/testfile0 | 1 + test/import-chain/data/testfile0 | 1 + test/import-chain/data/testfile1 | 1 + test/import-chain/test-template.json | 35 ++++++++++++++++++++++ 14 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/scribe/chain.go create mode 100644 test/concat/data/dir0/testfile0 create mode 100644 test/import-chain/Makefile create mode 100644 test/import-chain/data/dir0/testfile0 create mode 100644 test/import-chain/data/testfile0 create mode 100644 test/import-chain/data/testfile1 create mode 100644 test/import-chain/test-template.json diff --git a/src/scribe/chain.go b/src/scribe/chain.go new file mode 100644 index 0000000..49dbd35 --- /dev/null +++ b/src/scribe/chain.go @@ -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 +} diff --git a/src/scribe/document.go b/src/scribe/document.go index 6ca17f4..53fb57c 100644 --- a/src/scribe/document.go +++ b/src/scribe/document.go @@ -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 } diff --git a/src/scribe/filecontent.go b/src/scribe/filecontent.go index 5906165..570ac45 100644 --- a/src/scribe/filecontent.go +++ b/src/scribe/filecontent.go @@ -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 } diff --git a/src/scribe/filename.go b/src/scribe/filename.go index b2e0f90..db31451 100644 --- a/src/scribe/filename.go +++ b/src/scribe/filename.go @@ -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") diff --git a/src/scribe/object.go b/src/scribe/object.go index a6aaa76..42c3d0a 100644 --- a/src/scribe/object.go +++ b/src/scribe/object.go @@ -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 } diff --git a/src/scribe/package.go b/src/scribe/package.go index ad4a404..4cda226 100644 --- a/src/scribe/package.go +++ b/src/scribe/package.go @@ -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{} diff --git a/src/scribe/raw.go b/src/scribe/raw.go index ec6c14a..99f2bd4 100644 --- a/src/scribe/raw.go +++ b/src/scribe/raw.go @@ -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") diff --git a/test/Makefile b/test/Makefile index f62aa03..9d8b3ea 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,4 @@ -TESTDIRS = filecontent filename package concat raw evrtest +TESTDIRS = filecontent filename package concat raw import-chain evrtest all: diff --git a/test/concat/data/dir0/testfile0 b/test/concat/data/dir0/testfile0 new file mode 100644 index 0000000..4bf16a5 --- /dev/null +++ b/test/concat/data/dir0/testfile0 @@ -0,0 +1 @@ +var = (1, 5) diff --git a/test/import-chain/Makefile b/test/import-chain/Makefile new file mode 100644 index 0000000..df69fd4 --- /dev/null +++ b/test/import-chain/Makefile @@ -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 diff --git a/test/import-chain/data/dir0/testfile0 b/test/import-chain/data/dir0/testfile0 new file mode 100644 index 0000000..4bf16a5 --- /dev/null +++ b/test/import-chain/data/dir0/testfile0 @@ -0,0 +1 @@ +var = (1, 5) diff --git a/test/import-chain/data/testfile0 b/test/import-chain/data/testfile0 new file mode 100644 index 0000000..4bf16a5 --- /dev/null +++ b/test/import-chain/data/testfile0 @@ -0,0 +1 @@ +var = (1, 5) diff --git a/test/import-chain/data/testfile1 b/test/import-chain/data/testfile1 new file mode 100644 index 0000000..62615e6 --- /dev/null +++ b/test/import-chain/data/testfile1 @@ -0,0 +1 @@ +minor = 8 diff --git a/test/import-chain/test-template.json b/test/import-chain/test-template.json new file mode 100644 index 0000000..7eab033 --- /dev/null +++ b/test/import-chain/test-template.json @@ -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" + } + ] +}