<commit_before>path = require 'path'
_ = require 'underscore-plus'
{Emitter, Subscriber} = require 'emissary'
fs = require 'fs-plus'
PathWatcher = require 'pathwatcher'
File = require './file'

module.exports =
class Directory
  Emitter.includeInto(this)
  Subscriber.includeInto(this)

  constructor: ({@name, fullPath, @symlink, @expandedEntries, @isExpanded, @isRoot}) ->
    @path = fullPath
    @isRoot ?= false
    @isExpanded ?= false
    @expandedEntries ?= {}
    @status = null
    @entries = {}

    @submodule = atom.project.getRepo()?.isSubmodule(@path)

    repo = atom.project.getRepo()
    if repo?
      @subscribeToRepo(repo)
      @updateStatus(repo)

  destroy: ->
    @unwatch()
    @unsubscribe()
    @emit 'destroyed'

  # Subscribe to the given repo for changes to the Git status of this directory.
  subscribeToRepo: (repo) ->
    @subscribe repo, 'status-changed', (changedPath, status) =>
      @updateStatus(repo) if changedPath.indexOf("#{@path}#{path.sep}") is 0
    @subscribe repo, 'statuses-changed', =>
      @updateStatus(repo)

  # Update the status property of this directory using the repo.
  updateStatus: (repo) ->
    newStatus = null
    if repo.isPathIgnored(@path)
      newStatus = 'ignored'
    else
      status = repo.getDirectoryStatus(@path)
      if repo.isStatusModified(status)
        newStatus = 'modified'
      else if repo.isStatusNew(status)
        newStatus = 'added'

    if newStatus isnt @status
      @status = newStatus
      @emit 'status-changed', newStatus

  # Is the given path ignored?
  isPathIgnored: (filePath) ->
    if atom.config.get('tree-view.hideVcsIgnoredFiles')
      repo = atom.project.getRepo()
      return true if repo? and repo.isProjectAtRoot() and repo.isPathIgnored(filePath)

    if atom.config.get('tree-view.hideIgnoredNames')
      ignoredNames = atom.config.get('core.ignoredNames') ? []
      ignoredNames = [ignoredNames] if typeof ignoredNames is 'string'
      name = path.basename(filePath)
      return true if _.contains(ignoredNames, name)
      extension = path.extname(filePath)
      return true if extension and _.contains(ignoredNames, "*#{extension}")

    false

  # Public: Does this directory contain the given path?
  #
  # See atom.Directory::contains for more details.
  contains: (pathToCheck) ->
    # @directory.contains(pathToCheck)

  # Public: Stop watching this directory for changes.
  unwatch: ->
    if @watchSubscription?
      @watchSubscription.close()
      @watchSubscription = null

    for key, entry of @entries
      entry.destroy()
      delete @entries[key]

  # Public: Watch this directory for changes.
  #
  # The changes will be emitted as 'entries-added' and 'entries-removed' events.
  watch: ->
    @watchSubscription ?= PathWatcher.watch @path, (eventType) =>
      switch eventType
        when 'change' then @reload()
        when 'delete' then @destroy()

  getEntries: ->
    names = fs.readdirSync(@path).sort (name1, name2) ->
      name1.toLowerCase().localeCompare(name2.toLowerCase())

    files = []
    directories = []

    for name in names
      fullPath = path.join(@path, name)
      continue if @isPathIgnored(fullPath)

      try
        stat = fs.lstatSync(fullPath)
        symlink = stat.isSymbolicLink()
        stat = fs.statSync(fullPath) if symlink

      if stat?.isDirectory()
        if @entries.hasOwnProperty(name)
          # push a placeholder since this entry already exists but this helps<commit_msg>Catch exceptions reading directory<commit_after>path = require 'path'
_ = require 'underscore-plus'
{Emitter, Subscriber} = require 'emissary'
fs = require 'fs-plus'
PathWatcher = require 'pathwatcher'
File = require './file'

module.exports =
class Directory
  Emitter.includeInto(this)
  Subscriber.includeInto(this)

  constructor: ({@name, fullPath, @symlink, @expandedEntries, @isExpanded, @isRoot}) ->
    @path = fullPath
    @isRoot ?= false
    @isExpanded ?= false
    @expandedEntries ?= {}
    @status = null
    @entries = {}

    @submodule = atom.project.getRepo()?.isSubmodule(@path)

    repo = atom.project.getRepo()
    if repo?
      @subscribeToRepo(repo)
      @updateStatus(repo)

  destroy: ->
    @unwatch()
    @unsubscribe()
    @emit 'destroyed'

  # Subscribe to the given repo for changes to the Git status of this directory.
  subscribeToRepo: (repo) ->
    @subscribe repo, 'status-changed', (changedPath, status) =>
      @updateStatus(repo) if changedPath.indexOf("#{@path}#{path.sep}") is 0
    @subscribe repo, 'statuses-changed', =>
      @updateStatus(repo)

  # Update the status property of this directory using the repo.
  updateStatus: (repo) ->
    newStatus = null
    if repo.isPathIgnored(@path)
      newStatus = 'ignored'
    else
      status = repo.getDirectoryStatus(@path)
      if repo.isStatusModified(status)
        newStatus = 'modified'
      else if repo.isStatusNew(status)
        newStatus = 'added'

    if newStatus isnt @status
      @status = newStatus
      @emit 'status-changed', newStatus

  # Is the given path ignored?
  isPathIgnored: (filePath) ->
    if atom.config.get('tree-view.hideVcsIgnoredFiles')
      repo = atom.project.getRepo()
      return true if repo? and repo.isProjectAtRoot() and repo.isPathIgnored(filePath)

    if atom.config.get('tree-view.hideIgnoredNames')
      ignoredNames = atom.config.get('core.ignoredNames') ? []
      ignoredNames = [ignoredNames] if typeof ignoredNames is 'string'
      name = path.basename(filePath)
      return true if _.contains(ignoredNames, name)
      extension = path.extname(filePath)
      return true if extension and _.contains(ignoredNames, "*#{extension}")

    false

  # Public: Does this directory contain the given path?
  #
  # See atom.Directory::contains for more details.
  contains: (pathToCheck) ->
    # @directory.contains(pathToCheck)

  # Public: Stop watching this directory for changes.
  unwatch: ->
    if @watchSubscription?
      @watchSubscription.close()
      @watchSubscription = null

    for key, entry of @entries
      entry.destroy()
      delete @entries[key]

  # Public: Watch this directory for changes.
  #
  # The changes will be emitted as 'entries-added' and 'entries-removed' events.
  watch: ->
    @watchSubscription ?= PathWatcher.watch @path, (eventType) =>
      switch eventType
        when 'change' then @reload()
        when 'delete' then @destroy()

  getEntries: ->
    try
      names = fs.readdirSync(@path)
    catch error
      names = []

    names.sort (name1, name2) -> name1.toLowerCase().localeCompare(name2.toLowerCase())

    files = []
    directories = []

    for name in names
      fullPath = path.join(@path, name)
      continue if @isPathIgnored(fullPath)

      try
        stat = fs.lstatSync(fullPath)
        symlink = stat.isSymbolicLink()
        stat = fs.statSync(fullPath) if symlink

      if stat?.isDirectory()
        if @entries.hasOwnProperty(name)
          # push a placeholder since this entry already exists but this helps
{'fraction_non_alphanumeric': 0.11424100156494522, 'fraction_numerical': 0.0014226774790155072, 'mean_word_length': 3.125586854460094, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6571606', 'n_tokens_mistral': 2118, 'n_tokens_neox': 2114, 'n_words': 565}