mirror of
https://github.com/atom/atom.git
synced 2026-01-24 14:28:14 -05:00
This allows us not to inject confirm or ApplicationDelegate into Project, GitRepositoryProvider, and GitRepository.
85 lines
3.3 KiB
CoffeeScript
85 lines
3.3 KiB
CoffeeScript
fs = require 'fs'
|
|
{Directory} = require 'pathwatcher'
|
|
GitRepository = require './git-repository'
|
|
|
|
# Returns the .gitdir path in the agnostic Git symlink .git file given, or
|
|
# null if the path is not a valid gitfile.
|
|
#
|
|
# * `gitFile` {String} path of gitfile to parse
|
|
gitFileRegex = RegExp "^gitdir: (.+)"
|
|
pathFromGitFile = (gitFile) ->
|
|
try
|
|
gitFileBuff = fs.readFileSync(gitFile, 'utf8')
|
|
return gitFileBuff?.match(gitFileRegex)[1]
|
|
|
|
# Checks whether a valid `.git` directory is contained within the given
|
|
# directory or one of its ancestors. If so, a Directory that corresponds to the
|
|
# `.git` folder will be returned. Otherwise, returns `null`.
|
|
#
|
|
# * `directory` {Directory} to explore whether it is part of a Git repository.
|
|
findGitDirectorySync = (directory) ->
|
|
# TODO: Fix node-pathwatcher/src/directory.coffee so the following methods
|
|
# can return cached values rather than always returning new objects:
|
|
# getParent(), getFile(), getSubdirectory().
|
|
gitDir = directory.getSubdirectory('.git')
|
|
gitDirPath = pathFromGitFile(gitDir.getPath?())
|
|
if gitDirPath
|
|
gitDir = new Directory(directory.resolve(gitDirPath))
|
|
if gitDir.existsSync?() and isValidGitDirectorySync gitDir
|
|
gitDir
|
|
else if directory.isRoot()
|
|
return null
|
|
else
|
|
findGitDirectorySync directory.getParent()
|
|
|
|
# Returns a boolean indicating whether the specified directory represents a Git
|
|
# repository.
|
|
#
|
|
# * `directory` {Directory} whose base name is `.git`.
|
|
isValidGitDirectorySync = (directory) ->
|
|
# To decide whether a directory has a valid .git folder, we use
|
|
# the heuristic adopted by the valid_repository_path() function defined in
|
|
# node_modules/git-utils/deps/libgit2/src/repository.c.
|
|
return directory.getSubdirectory('objects').existsSync() and
|
|
directory.getFile('HEAD').existsSync() and
|
|
directory.getSubdirectory('refs').existsSync()
|
|
|
|
# Provider that conforms to the atom.repository-provider@0.1.0 service.
|
|
module.exports =
|
|
class GitRepositoryProvider
|
|
|
|
constructor: (@project, @config) ->
|
|
# Keys are real paths that end in `.git`.
|
|
# Values are the corresponding GitRepository objects.
|
|
@pathToRepository = {}
|
|
|
|
# Returns a {Promise} that resolves with either:
|
|
# * {GitRepository} if the given directory has a Git repository.
|
|
# * `null` if the given directory does not have a Git repository.
|
|
repositoryForDirectory: (directory) ->
|
|
# TODO: Currently, this method is designed to be async, but it relies on a
|
|
# synchronous API. It should be rewritten to be truly async.
|
|
Promise.resolve(@repositoryForDirectorySync(directory))
|
|
|
|
# Returns either:
|
|
# * {GitRepository} if the given directory has a Git repository.
|
|
# * `null` if the given directory does not have a Git repository.
|
|
repositoryForDirectorySync: (directory) ->
|
|
# Only one GitRepository should be created for each .git folder. Therefore,
|
|
# we must check directory and its parent directories to find the nearest
|
|
# .git folder.
|
|
gitDir = findGitDirectorySync(directory)
|
|
unless gitDir
|
|
return null
|
|
|
|
gitDirPath = gitDir.getPath()
|
|
repo = @pathToRepository[gitDirPath]
|
|
unless repo
|
|
repo = GitRepository.open(gitDirPath, {@project, @config})
|
|
return null unless repo
|
|
repo.onDidDestroy(=> delete @pathToRepository[gitDirPath])
|
|
@pathToRepository[gitDirPath] = repo
|
|
repo.refreshIndex()
|
|
repo.refreshStatus()
|
|
repo
|