 git = require 'git-utils'
 
-repo = git.open '.'
+# git.open() returns null when we're not in a repo
+#
+# We're using false to represent "not yet created" and null to
+# represent "created and not in a repo"
+repoObj = false
+
+repo = ->
+  repoObj = git.open '.' if repoObj is false
+  repoObj
 
 module.exports = (Impromptu, register, git) ->
   # Expose the repo object from the git-utils library
   # This will be null when we're not in a repo
   register '_repo',
     update: (done) ->
-      done null, repo
+      done null, repo()
 
   # Helper to figure out if we're in a repo at all
   register 'isRepo',
     update: (done) ->
-      done null, !! repo
+      done null, !! repo()
 
   # Root path to the repository
   register 'root',
     update: (done) ->
-      root = repo?.getPath().replace /\.git\/$/, ''
+      root = repo()?.getPath().replace /\.git\/$/, ''
       done null, root
 
   # Branch name

  # Returns null in newly-initialized repos (note that isRepo() still returns true in this case)
  register 'branch',
    update: (done) ->
      branch = repo?.getShortHead()
      done null, branch

  # Determine whether the repo is currently in a detached head state
  # This happens when you checkout, for example, a commit hash
  register 'isDetachedHead',
    update: (done) ->
      branch = repo?.getHead()
      done null, ! /^refs\/heads\//.test branch

  # Returns an object with 'ahead' and 'behind' keys

  # This command *must* be passed through a formatter before its displayed
  register '_status',
    update: (done) ->
      return done null, [] unless status = repo()?.getStatus()

      statuses = for path, code of status
        # Hack around weird behavior in libgit2 that treats nested Git repos as submodules
        # https://github.com/libgit2/libgit2/pull/1423
        #
        # Benchmarking suggests this is likely fast enough
        continue if repo().isIgnored path

        new Status path, code

