Introduce atom.directory-provider service.

A `Project` will always have a `DefaultDirectoryProvider` that
will be used if there are no other `DirectoryProvider` objects
that can produce a `Directory` for a path.
This commit is contained in:
Michael Bolin
2015-02-12 15:47:09 -08:00
parent 97f43a3335
commit c728ad6d57
3 changed files with 75 additions and 13 deletions

View File

@@ -0,0 +1,21 @@
DefaultDirectoryProvider = require "../src/default-directory-provider"
path = require "path"
temp = require "temp"
describe "DefaultDirectoryProvider", ->
describe ".directoryForURISync(uri)", ->
it "returns a Directory with a path that matches the uri", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
directory = provider.directoryForURISync(tmp)
expect(directory.getPath()).toEqual tmp
describe ".directoryForURI(uri)", ->
it "returns a Promise that resolves to a Directory with a path that matches the uri", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
waitsForPromise ->
provider.directoryForURI(tmp).then (directory) ->
expect(directory.getPath()).toEqual tmp

View File

@@ -0,0 +1,33 @@
{Directory} = require 'pathwatcher'
fs = require 'fs-plus'
path = require 'path'
module.exports =
class DefaultDirectoryProvider
# Public: Create a Directory that corresponds to the specified URI.
#
# * `uri` {String} The path to the directory to add. This is guaranteed not to
# be contained by a {Directory} in `atom.project`.
# Returns:
# * {Directory} if the given URI is compatible with this provider.
# * `null` if the given URI is not compatibile with this provider.
directoryForURISync: (uri) ->
projectPath = path.normalize(uri)
directoryPath = if fs.isDirectorySync(projectPath)
projectPath
else
path.dirname(projectPath)
new Directory(directoryPath)
# Public: Create a Directory that corresponds to the specified URI.
#
# * `uri` {String} The path to the directory to add. This is guaranteed not to
# be contained by a {Directory} in `atom.project`.
# Returns a Promise that resolves to:
# * {Directory} if the given URI is compatible with this provider.
# * `null` if the given URI is not compatibile with this provider.
directoryForURI: (uri) ->
Promise.resolve(@directoryForURISync(uri))

View File

@@ -8,9 +8,9 @@ Q = require 'q'
{Model} = require 'theorist'
{Subscriber} = require 'emissary'
{Emitter} = require 'event-kit'
DefaultDirectoryProvider = require './default-directory-provider'
Serializable = require 'serializable'
TextBuffer = require 'text-buffer'
{Directory} = require 'pathwatcher'
Grim = require 'grim'
TextEditor = require './text-editor'
@@ -41,6 +41,14 @@ class Project extends Model
@rootDirectories = []
@repositories = []
@directoryProviders = [new DefaultDirectoryProvider()]
atom.packages.serviceHub.consume(
'atom.directory-provider',
'^0.1.0',
# New providers are added to the front of @directoryProviders because
# DefaultDirectoryProvider is a catch-all that will always provide a Directory.
(provider) => @directoryProviders.unshift(provider))
# Mapping from the real path of a {Directory} to a {Promise} that resolves
# to either a {Repository} or null. Ideally, the {Directory} would be used
# as the key; however, there can be multiple {Directory} objects created for
@@ -182,22 +190,22 @@ class Project extends Model
Grim.deprecate("Use ::setPaths instead")
@setPaths([path])
# Public: Add a path the project's list of root paths
# Public: Add a path to the project's list of root paths
#
# * `projectPath` {String} The path to the directory to add.
addPath: (projectPath, options) ->
projectPath = path.normalize(projectPath)
for directory in @getDirectories()
# Apparently a Directory does not believe it can contain itself, so we
# must also check whether the paths match.
return if directory.contains(projectPath) or directory.getPath() is projectPath
directoryPath = if fs.isDirectorySync(projectPath)
projectPath
else
path.dirname(projectPath)
return if @getPaths().some (existingPath) ->
(directoryPath is existingPath) or
(directoryPath.indexOf(path.join(existingPath, path.sep)) is 0)
directory = new Directory(directoryPath)
directory = null
for provider in @directoryProviders
break if directory = provider.directoryForURISync?(projectPath)
if directory is null
# This should never happen because DefaultDirectoryProvider should always
# return a Directory.
throw new Error(projectPath + ' could not be resolved to a directory')
@rootDirectories.push(directory)
repo = null