FS_Win32.java

  1. /*
  2.  * Copyright (C) 2009, Google Inc.
  3.  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
  4.  *
  5.  * This program and the accompanying materials are made available under the
  6.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  7.  * https://www.eclipse.org/org/documents/edl-v10.php.
  8.  *
  9.  * SPDX-License-Identifier: BSD-3-Clause
  10.  */

  11. package org.eclipse.jgit.util;

  12. import java.io.File;
  13. import java.io.IOException;
  14. import java.nio.file.FileVisitOption;
  15. import java.nio.file.FileVisitResult;
  16. import java.nio.file.Files;
  17. import java.nio.file.LinkOption;
  18. import java.nio.file.Path;
  19. import java.nio.file.SimpleFileVisitor;
  20. import java.nio.file.attribute.BasicFileAttributes;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.EnumSet;
  24. import java.util.List;

  25. import org.eclipse.jgit.errors.CommandFailedException;
  26. import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
  27. import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy;
  28. import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry;
  29. import org.slf4j.Logger;
  30. import org.slf4j.LoggerFactory;


  31. /**
  32.  * FS implementation for Windows
  33.  *
  34.  * @since 3.0
  35.  */
  36. public class FS_Win32 extends FS {
  37.     private static final Logger LOG = LoggerFactory.getLogger(FS_Win32.class);

  38.     /**
  39.      * Constructor
  40.      */
  41.     public FS_Win32() {
  42.         super();
  43.     }

  44.     /**
  45.      * Constructor
  46.      *
  47.      * @param src
  48.      *            instance whose attributes to copy
  49.      */
  50.     protected FS_Win32(FS src) {
  51.         super(src);
  52.     }

  53.     /** {@inheritDoc} */
  54.     @Override
  55.     public FS newInstance() {
  56.         return new FS_Win32(this);
  57.     }

  58.     /** {@inheritDoc} */
  59.     @Override
  60.     public boolean supportsExecute() {
  61.         return false;
  62.     }

  63.     /** {@inheritDoc} */
  64.     @Override
  65.     public boolean canExecute(File f) {
  66.         return false;
  67.     }

  68.     /** {@inheritDoc} */
  69.     @Override
  70.     public boolean setExecute(File f, boolean canExec) {
  71.         return false;
  72.     }

  73.     /** {@inheritDoc} */
  74.     @Override
  75.     public boolean isCaseSensitive() {
  76.         return false;
  77.     }

  78.     /** {@inheritDoc} */
  79.     @Override
  80.     public boolean retryFailedLockFileCommit() {
  81.         return true;
  82.     }

  83.     /** {@inheritDoc} */
  84.     @Override
  85.     public Entry[] list(File directory, FileModeStrategy fileModeStrategy) {
  86.         if (!Files.isDirectory(directory.toPath(), LinkOption.NOFOLLOW_LINKS)) {
  87.             return NO_ENTRIES;
  88.         }
  89.         List<Entry> result = new ArrayList<>();
  90.         FS fs = this;
  91.         boolean checkExecutable = fs.supportsExecute();
  92.         try {
  93.             Files.walkFileTree(directory.toPath(),
  94.                     EnumSet.noneOf(FileVisitOption.class), 1,
  95.                     new SimpleFileVisitor<Path>() {
  96.                         @Override
  97.                         public FileVisitResult visitFile(Path file,
  98.                                 BasicFileAttributes attrs) throws IOException {
  99.                             File f = file.toFile();
  100.                             FS.Attributes attributes = new FS.Attributes(fs, f,
  101.                                     true, attrs.isDirectory(),
  102.                                     checkExecutable && f.canExecute(),
  103.                                     attrs.isSymbolicLink(),
  104.                                     attrs.isRegularFile(),
  105.                                     attrs.creationTime().toMillis(),
  106.                                     attrs.lastModifiedTime().toInstant(),
  107.                                     attrs.size());
  108.                             result.add(new FileEntry(f, fs, attributes,
  109.                                     fileModeStrategy));
  110.                             return FileVisitResult.CONTINUE;
  111.                         }

  112.                         @Override
  113.                         public FileVisitResult visitFileFailed(Path file,
  114.                                 IOException exc) throws IOException {
  115.                             // Just ignore it
  116.                             return FileVisitResult.CONTINUE;
  117.                         }
  118.                     });
  119.         } catch (IOException e) {
  120.             // Ignore
  121.         }
  122.         if (result.isEmpty()) {
  123.             return NO_ENTRIES;
  124.         }
  125.         return result.toArray(new Entry[0]);
  126.     }

  127.     /** {@inheritDoc} */
  128.     @Override
  129.     protected File discoverGitExe() {
  130.         String path = SystemReader.getInstance().getenv("PATH"); //$NON-NLS-1$
  131.         File gitExe = searchPath(path, "git.exe", "git.cmd"); //$NON-NLS-1$ //$NON-NLS-2$

  132.         if (gitExe == null) {
  133.             if (searchPath(path, "bash.exe") != null) { //$NON-NLS-1$
  134.                 // This isn't likely to work, but its worth trying:
  135.                 // If bash is in $PATH, git should also be in $PATH.
  136.                 String w;
  137.                 try {
  138.                     w = readPipe(userHome(),
  139.                             new String[] { "bash", "--login", "-c", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  140.                                     "which git" }, // //$NON-NLS-1$
  141.                             SystemReader.getInstance().getDefaultCharset()
  142.                                     .name());
  143.                 } catch (CommandFailedException e) {
  144.                     LOG.warn(e.getMessage());
  145.                     return null;
  146.                 }
  147.                 if (!StringUtils.isEmptyOrNull(w)) {
  148.                     // The path may be in cygwin/msys notation so resolve it right away
  149.                     gitExe = resolve(null, w);
  150.                 }
  151.             }
  152.         }

  153.         return gitExe;
  154.     }

  155.     /** {@inheritDoc} */
  156.     @Override
  157.     protected File userHomeImpl() {
  158.         String home = SystemReader.getInstance().getenv("HOME"); //$NON-NLS-1$
  159.         if (home != null) {
  160.             return resolve(null, home);
  161.         }
  162.         String homeDrive = SystemReader.getInstance().getenv("HOMEDRIVE"); //$NON-NLS-1$
  163.         if (homeDrive != null) {
  164.             String homePath = SystemReader.getInstance().getenv("HOMEPATH"); //$NON-NLS-1$
  165.             if (homePath != null) {
  166.                 return new File(homeDrive, homePath);
  167.             }
  168.         }

  169.         String homeShare = SystemReader.getInstance().getenv("HOMESHARE"); //$NON-NLS-1$
  170.         if (homeShare != null) {
  171.             return new File(homeShare);
  172.         }

  173.         return super.userHomeImpl();
  174.     }

  175.     /** {@inheritDoc} */
  176.     @Override
  177.     public ProcessBuilder runInShell(String cmd, String[] args) {
  178.         List<String> argv = new ArrayList<>(3 + args.length);
  179.         argv.add("cmd.exe"); //$NON-NLS-1$
  180.         argv.add("/c"); //$NON-NLS-1$
  181.         argv.add(cmd);
  182.         argv.addAll(Arrays.asList(args));
  183.         ProcessBuilder proc = new ProcessBuilder();
  184.         proc.command(argv);
  185.         return proc;
  186.     }

  187.     /** {@inheritDoc} */
  188.     @Override
  189.     public Attributes getAttributes(File path) {
  190.         return FileUtils.getFileAttributesBasic(this, path);
  191.     }
  192. }