code: package com.beijunyi.parallelgit.filesystem;
  
  import java.io.IOException;
  import java.nio.file.*;
  import java.nio.file.attribute.UserPrincipalLookupService;
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Set;
  import javax.annotation.Nonnull;
  import javax.annotation.Nullable;
  
  import com.beijunyi.parallelgit.filesystem.io.RootNode;
  import com.beijunyi.parallelgit.filesystem.utils.GfsConfiguration;
  import com.beijunyi.parallelgit.utils.RefUtils;
  import org.eclipse.jgit.lib.ObjectId;
  import org.eclipse.jgit.lib.Repository;
  import org.eclipse.jgit.revwalk.RevCommit;
  
  import static com.beijunyi.parallelgit.filesystem.io.GfsFileAttributeView.Basic.BASIC_VIEW;
  import static com.beijunyi.parallelgit.filesystem.io.GfsFileAttributeView.Posix.POSIX_VIEW;
  import static java.util.Arrays.asList;
  import static java.util.Collections.unmodifiableSet;
  import static org.eclipse.jgit.lib.Constants.MASTER;
  
  public class GitFileSystem extends FileSystem {
  
    public static final Set<String> SUPPORTED_VIEWS = unmodifiableSet(new HashSet<>(asList(BASIC_VIEW, POSIX_VIEW)));
  
    private final String sid;
    private final GfsObjectService objService;
    private final GfsFileStore fileStore;
    private final GfsStatusProvider statusProvider;
  
    private boolean closed = false;
  
    public GitFileSystem(GfsConfiguration cfg, String sid) throws IOException {
      this.sid = sid;
      objService = new GfsObjectService(cfg.repository());
      RevCommit commit = cfg.commit();
      String branch = cfg.branch();
      if(branch == null && commit == null)
        branch = RefUtils.fullBranchName(MASTER);
      fileStore = new GfsFileStore(commit, objService);
      statusProvider = new GfsStatusProvider(fileStore, branch, commit);
    }
  
    @Nonnull
    @Override
    public GitFileSystemProvider provider() {
      return GitFileSystemProvider.getDefault();
    }
  
    @Override
    public synchronized void close() {
      if(!closed) {
        closed = true;
        objService.close();
        statusProvider.close();
        GitFileSystemProvider.getDefault().unregister(this);
      }
    }
  
    @Override
    public synchronized boolean isOpen() {
      return !closed;
    }
  
    @Override
    public boolean isReadOnly() {
      return false;
    }
  
    @Nonnull
    @Override
    public String getSeparator() {
      return "/";
    }
  
    @Nonnull
    @Override
    public Iterable<Path> getRootDirectories() {
      return Collections.<Path>singleton(getRootPath());
    }
  
    @Nonnull
    @Override
    public Iterable<FileStore> getFileStores() {
      return Collections.<FileStore>singleton(fileStore);
    }
  
    @Nonnull
    @Override
    public Set<String> supportedFileAttributeViews() {
      return SUPPORTED_VIEWS;
    }
  
    @Nonnull
    @Override
    public GitPath getPath(String first, String... more) {
      String path;
      if(more.length == 0) {
        path = first;
      } else {
        StringBuilder sb = new StringBuilder();
        sb.append(first);
        for(String segment: more) {
          if(segment.length() > 0) {
            if(sb.length() > 0) sb.append('/');
            sb.append(segment);
          }
        }
        path = sb.toString();
      }
      return new GitPath(this, path);
    }
  
    @Nonnull
    @Override
    public PathMatcher getPathMatcher(String syntaxAndInput) {
      return GfsPathMatcher.newMatcher(syntaxAndInput);
    }
  
    @Nullable
    @Override
    public UserPrincipalLookupService getUserPrincipalLookupService() throws UnsupportedOperationException {
      throw new UnsupportedOperationException();
    }
  
    @Nullable
    @Override
    public WatchService newWatchService() throws UnsupportedOperationException {
      throw new UnsupportedOperationException();
    }
  
    @Nonnull
    public Repository getRepository() {
      return objService.getRepository();
    }
  
    @Nonnull
    public String getSessionId() {
      return sid;
    }
  
    @Nonnull
    public GitPath getRootPath() {
      return getPath("/");
    }
  
    @Nonnull
    public GfsObjectService getObjectService() {
      return objService;
    }
  
    @Nonnull
    public GfsFileStore getFileStore() {
      return fileStore;
    }
  
    @Nonnull
    public GfsStatusProvider getStatusProvider() {
      return statusProvider;
    }
  
    @Nonnull
    public ObjectId flush() throws IOException {
      RootNode root = fileStore.getRoot();
      ObjectId ret = root.getObjectId(true);
      objService.flush();
      return ret;
    }
  
    public void updateOrigin(ObjectId rootTree) throws IOException {
      RootNode root = fileStore.getRoot();
      root.updateOrigin(rootTree);
    }
  
    public void reset() throws IOException {
      RootNode root = fileStore.getRoot();
      root.reset();
    }
  
    @Override
    public boolean equals(@Nullable Object that) {
      return this == that
               || (that != null && getClass() == that.getClass() && sid.equals(((GitFileSystem)that).sid));
  
    }
  
    @Override
    public int hashCode() {
      return sid.hashCode();
    }
  
    @Override
    protected void finalize() throws Throwable {
      super.finalize();
      close();
    }
  
  }
  