Last active
March 1, 2017 20:26
-
-
Save joliss/e46516c5e019d5c431546c41506c881f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// module: fso, for in-memory file system objects | |
// FSObject is the raw object that will be part of the | |
// internal Broccoli plugin API. Need better name? | |
// (Git terminology: File = blob, Directory = tree, | |
// FSObject = object.) | |
class FSObject { } | |
class File extends FSObject { | |
executable: bool | |
revision: int // mtime and size go into this; like a hash in a Merkle tree but fast | |
contentLocation: string // absolute path on disk | |
} | |
class Directory extends FSObject { | |
revision: int // max of all child revision | |
entries: Map<string, FSObject> // string is a single path segment, e.g. "src" | |
} | |
// want this in a shared node module | |
fso.read(path) -> FSObject | |
fso.write(path, fsObject) | |
fso.update(path, oldFsObject, newFsObject) | |
// in broccoli-plugin subclasses: | |
// easy to implement: | |
this.fs.statSync(this.in[0], 'src/foo.js') | |
// With facade. Harder to implement but cuter: | |
this.in[0].statSync('src/foo.js') | |
// Want to be able to pass things forward: | |
this.out.copy(someFsObject, 'foo/bar') // can be file or directory | |
// someFileObject.contentLocation could point anywhere. Are we OK not really | |
// knowing where it came from? | |
this.out.symlinkSync('ourCacheDir/bar.js', 'foo/bar.js') | |
// creates a new File object with { contentLocation: 'ourCacheDir/bar.js' } | |
this.out.writeSync('foo/bar.js', 'some text') | |
// We actually write to outputPath/foo/bar.js, and do | |
// this.out.get('foo').set('bar.js', new File(contentLocation: '.../foo/bar.js')) | |
// On every build, we start with a new empty this.out | |
// Is this.cache an FSObject cache? | |
this.cache.writeSync('dir1/foo.js', '// foo') | |
this.cache.copy(someFsObjectFromThisDotIn, 'dir2/foo') | |
// dir2/foo might become stale, but the answer is perhaps simply | |
// "don't do this" -- make sure you don't keep stale objects around | |
// or you'll get FileNotFound errors because contentLocation goes invalid | |
// Cache invalidation pattern: | |
oldCache = this.cache.get('current') | |
this.cache.mkdir('new') | |
newCache = this.cache.get('new') | |
// Iterate over input, copy stuff from oldCache to newCache. | |
// At the end, overwrite current with new: | |
this.cache.move('new', 'current') | |
// Can get stuff that FSTree consumes: | |
this.in[0].getEntries() | |
// To start implementing: | |
// broccoli-plugin can start implementing some facade like this and just | |
// always read and write from disk for compat. | |
// Gives us incremental outputPath updating, but no savings on reading. | |
// Once we're happy, we turn the underlying FSObject into an official | |
// Broccoli API: | |
// Let's not sniff like this: | |
this.inputNodes[0].out // brittle! | |
this.inputNodes[0].__broccoliGetInfo__ // still brittle! | |
// Then add feature flag: fsobject | |
// Broccoli core: | |
// calls fso.read/fso.write as needed | |
// broccoli-plugin: | |
// can request physical files or FSObjects from Broccoli core | |
// call fso.read/fso.write only to deal with old Builder versions (compat) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment