code: package com.beijunyi.parallelgit.filesystem;
  
  import java.io.Closeable;
  import java.io.IOException;
  import java.nio.file.ClosedFileSystemException;
  import java.util.concurrent.locks.ReentrantLock;
  import javax.annotation.Nonnull;
  import javax.annotation.Nullable;
  
  import com.beijunyi.parallelgit.filesystem.exceptions.NoBranchException;
  import com.beijunyi.parallelgit.filesystem.exceptions.NoHeadCommitException;
  import com.beijunyi.parallelgit.filesystem.merge.MergeNote;
  import com.beijunyi.parallelgit.utils.RefUtils;
  import org.eclipse.jgit.revwalk.RevCommit;
  
  import static org.eclipse.jgit.lib.Constants.R_HEADS;
  
  public class GfsStatusProvider implements AutoCloseable {
  
    private final ReentrantLock lock = new ReentrantLock();
  
    private final GfsFileStore fileStore;
  
    private String branch;
    private RevCommit commit;
    private MergeNote mergeNote;
  
    private volatile boolean closed = false;
  
    public GfsStatusProvider(GfsFileStore fileStore, @Nullable String branch, @Nullable RevCommit commit) {
      this.fileStore = fileStore;
      this.commit = commit;
      this.branch = branch;
    }
  
    public boolean isDirty() throws IOException {
      return fileStore.getRoot().isModified();
    }
  
    @Nonnull
    public Update prepareUpdate() {
      return new Update();
    }
  
    @Nonnull
    public String branch() {
      checkClosed();
      if(branch == null)
        throw new NoBranchException();
      return branch.substring(R_HEADS.length());
    }
  
    public boolean isAttached() {
      return branch != null;
    }
  
    @Nonnull
    public RevCommit commit() {
      checkClosed();
      if(commit == null)
        throw new NoHeadCommitException();
      return commit;
    }
  
    public boolean isInitialized() {
      return branch != null;
    }
  
    @Nullable
    public MergeNote mergeNote() {
      checkClosed();
      return mergeNote;
    }
  
    @Override
    public synchronized void close() {
      if(!closed) closed = true;
    }
  
    private void checkClosed() {
      if(closed) throw new ClosedFileSystemException();
    }
  
    public class Update implements Closeable {
  
      private Update() {
        lock.lock();
      }
  
      @Override
      public void close() {
        lock.unlock();
      }
  
      @Nonnull
      public Update branch(String newBranch) {
        checkClosed();
        branch = RefUtils.fullBranchName(newBranch);
        return this;
      }
  
      @Nonnull
      public Update detach() {
        checkClosed();
        branch = null;
        return this;
      }
  
      @Nonnull
      public Update commit(RevCommit newCommit) {
        checkClosed();
        commit = newCommit;
        return this;
      }
  
      @Nonnull
      public Update mergeNote(MergeNote newMergeNote) {
        checkClosed();
        mergeNote = newMergeNote;
        return this;
      }
  
      @Nonnull
      public Update clearMergeNote() {
        checkClosed();
        mergeNote = null;
        return this;
      }
  
    }
  
  }
  