Skip to content

Instantly share code, notes, and snippets.

@jviereck
Forked from Gozala/filesystem.md
Created April 16, 2010 13:38
Show Gist options
  • Save jviereck/368412 to your computer and use it in GitHub Desktop.
Save jviereck/368412 to your computer and use it in GitHub Desktop.

Filesystem

Overview

Filesystem is one of the core components of Bespin, providing high-level API for files / directory manipulations. It is a wrapper of FileSources a low-level files / directory access providers.

Filesystem API is exposed to the plugins through editorapp module's files property and through the same named property on env object / argument that is passed to the extension endpoints.

Proposal

Filesystem can allow FileSource "mounting" to any given point on the filesystem, or on a custom URI scheme, much like it is in unix. This will allow plugins to expose access to a different resources in a standard manner just by implementing a few core filesource access functions. Good plugin examples may be:

  • Github plugin exposing user gists under certain mounting point
  • Jetpack based plugin exposing a local file system.

Plugins interested in providing custom filsources would have to provide "filsource" extension point pointing to an instance of FileSource. Instance can be created form FileSource class, by providing a set of methods mentioned in the next section to FileSource.create. FileSource class all of most the optional methods on top of mandatory ones. Obviously plugin providers are in power to override them to achieve more efficiency by introducing optimizations specific to their scenarios. Big part of the FileSystem will be move to a FileSource. FileSystem will take a role of a router between mounted FileSystems.

Specification

###Filesystem###

  • mount(pathOrURIScheme:String, fileSource:FileSource)
    Mounts filesource to a specified path / uri scheme. After successful mount all the file filesystem operations on the subpaths will be done using registered fileSource. In case if multiple filesystems will end up being mounted to the same mounting point the last registered will be used.

    • pathOrURIScheme - String representing one of of the followings:
      • '/' Root of the filesystem
      • Path representing an entry of the existing directory in the filesystem (Assuming that filesystem root exists even if no filesource is mounted yet.)
      • Custom uri scheme like "gist:"
    • fileSource - Object implementing FileSource interface (described in next section)
  • unmount(pathOrURIScheme:String, fileSource:FileSource)
    Unmounts filesource from specified path / uri scheme if it was mounted before. If this fileSource was overriding another one after unmount previously overrided filesystem will become active.

###FileSource###

Mandatory

  • invalidate(path:String)
  • read(path:String):Promise
  • write(path:String):Promise
  • list(path:String):Promise
  • remove(path:String):Promise
  • makeDirectory(path:String):Promise

Optional (may provide faster implementation)

  • isFile(path:String):Promise
  • isDirectory(path:String):Promise
  • rename(path:String, name:String):Promise
  • move(path):Promise
  • makeTree(path):Promise
  • copy(source, target):Promise
  • copyTree(source, target):Promise
  • listTree(path):Promise

Example

Plugins example "define metadata";

{
    "description": "Provides the gist filesystem",
    "dependencies": {
        "filesystem": "0.0",
		"settings": "0.0",
        "github": "0.0"
    },
    "provides": [
        {
            "ep": "filesource",
            "name": "gist",
            "pointer": "#source"
        }
    ]
}
"end";

var Promise = require('bespin:promise').Promise;
var FileSource = require('filesystem').FileSource;
var gist = require('github/yql-gist'); 
var settings = require('settings').settings;

var user = settings.get("github-user");
var token = settings.get("github-token");

function getId(path) {
	return path.substr(path.lastIndexOf('/'));
}
exports.source = FileSource.create({
    mountPoint: "/gists/",
	read: function(path) {
		var result = new Promise();
		gist.read({
			repo: getId(path),
			user: user,
			token: token
		}, function(content) {
			result.resolve(content);
		}, promise.reject)
		return result;
	},
	write: function(path, content) {
		var result = new Promise();
		gist.write({
			repo: getId(path),
			user: user,
			token: token,
			content: content
		}, function(id) {
			result.resolve(this.mountPoint + id);
		}, promise.reject)
		return result;
	},
	list: function(path) {
		var result = new Promise();
		gist.write({
			user: user,
			token: token
		}, function(gists) {
			result.resolve(gists.map(function(id)
				return this.mountPoint + id;
			));
		}, promise.reject)
		return result;
	},
	remove: function(path) {
		var result = new Promise();
		gist.remove({
			repo: getId(path),
			user: user,
			token: token
		}, result.resolve, promise.reject)
		return result;
	}
	makeDirectory: function(path) {
		// You can't have dirs in 
	},
	invalidate: function(path) {
		// I don't cache anything so not much to invalidate
	}
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment