import java.io.File;
import java.io.IOException;
-import org.eclipse.jgit.util.FS;
-
/**
* FS implementation for Java7 on unix like systems
*/
public void createSymLink(File path, String target) throws IOException {
FileUtil.createSymLink(path, target);
}
+
+ /**
+ * @since 3.3
+ */
+ @Override
+ public Attributes getAttributes(File path) {
+ return FileUtil.getFileAttributesPosix(this, path);
+ }
}
public void createSymLink(File path, String target) throws IOException {
FileUtil.createSymLink(path, target);
}
+
+ /**
+ * @since 3.3
+ */
+ @Override
+ public Attributes getAttributes(File path) {
+ return FileUtil.getFileAttributesBasic(this, path);
+ }
}
public void createSymLink(File path, String target) throws IOException {
FileUtil.createSymLink(path, target);
}
+
+ /**
+ * @since 3.3
+ */
+ @Override
+ public Attributes getAttributes(File path) {
+ return FileUtil.getFileAttributesBasic(this, path);
+ }
}
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.util.FS.Attributes;
class FileUtil {
+ static class Java7BasicAttributes extends Attributes {
+
+ Java7BasicAttributes(FS fs, File fPath, boolean exists,
+ boolean isDirectory, boolean isExecutable,
+ boolean isSymbolicLink, boolean isRegularFile,
+ long creationTime, long lastModifiedTime, long length) {
+ super(fs, fPath, exists, isDirectory, isExecutable, isSymbolicLink,
+ isRegularFile, creationTime, lastModifiedTime, length);
+ }
+ }
+
static String readSymlink(File path) throws IOException {
Path nioPath = path.toPath();
Path target = Files.readSymbolicLink(nioPath);
Files.delete(nioPath);
}
+ static Attributes getFileAttributesBasic(FS fs, File path) {
+ try {
+ Path nioPath = path.toPath();
+ BasicFileAttributes readAttributes = nioPath
+ .getFileSystem()
+ .provider()
+ .getFileAttributeView(nioPath,
+ BasicFileAttributeView.class,
+ LinkOption.NOFOLLOW_LINKS).readAttributes();
+ Attributes attributes = new FileUtil.Java7BasicAttributes(fs, path,
+ true,
+ readAttributes.isDirectory(),
+ fs.supportsExecute() ? path.canExecute() : false,
+ readAttributes.isSymbolicLink(),
+ readAttributes.isRegularFile(), //
+ readAttributes.creationTime().toMillis(), //
+ readAttributes.lastModifiedTime().toMillis(),
+ readAttributes.isSymbolicLink() ? Constants
+ .encode(FileUtils.readSymLink(path)).length
+ : readAttributes.size());
+ return attributes;
+ } catch (NoSuchFileException e) {
+ return new FileUtil.Java7BasicAttributes(fs, path, false, false,
+ false, false, false, 0L, 0L, 0L);
+ } catch (IOException e) {
+ return new Attributes(path, fs);
+ }
+ }
+
+ static Attributes getFileAttributesPosix(FS fs, File path) {
+ try {
+ Path nioPath = path.toPath();
+ PosixFileAttributes readAttributes = nioPath
+ .getFileSystem()
+ .provider()
+ .getFileAttributeView(nioPath,
+ PosixFileAttributeView.class,
+ LinkOption.NOFOLLOW_LINKS).readAttributes();
+ Attributes attributes = new FileUtil.Java7BasicAttributes(
+ fs,
+ path,
+ true, //
+ readAttributes.isDirectory(), //
+ readAttributes.permissions().contains(
+ PosixFilePermission.OWNER_EXECUTE),
+ readAttributes.isSymbolicLink(),
+ readAttributes.isRegularFile(), //
+ readAttributes.creationTime().toMillis(), //
+ readAttributes.lastModifiedTime().toMillis(),
+ readAttributes.size());
+ return attributes;
+ } catch (NoSuchFileException e) {
+ return new FileUtil.Java7BasicAttributes(fs, path, false, false,
+ false, false, false, 0L, 0L, 0L);
+ } catch (IOException e) {
+ return new Attributes(path, fs);
+ }
+ }
+
}
@Override
public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) {
return new FileTreeIteratorWithTimeControl(this,
- ((FileEntry) current()).file, fs, modTimes);
+ ((FileEntry) current()).getFile(), fs, modTimes);
}
@Override
@Override
public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader)
throws IncorrectObjectTypeException, IOException {
- return new FileTreeIterator(this, ((FileEntry) current()).file, fs);
+ return new FileTreeIterator(this, ((FileEntry) current()).getFile(), fs);
}
private Entry[] entries() {
* Wrapper for a standard Java IO file
*/
static public class FileEntry extends Entry {
- final File file;
-
private final FileMode mode;
- private long length = -1;
-
- private long lastModified;
+ private FS.Attributes attributes;
private FS fs;
* file system
*/
public FileEntry(final File f, FS fs) {
- file = f;
this.fs = fs;
-
- @SuppressWarnings("hiding")
- FileMode mode = null;
- try {
- if (fs.isSymLink(f)) {
- mode = FileMode.SYMLINK;
- } else if (fs.isDirectory(f)) {
- if (fs.exists(new File(f, Constants.DOT_GIT)))
- mode = FileMode.GITLINK;
- else
- mode = FileMode.TREE;
- } else if (fs.canExecute(file))
- mode = FileMode.EXECUTABLE_FILE;
+ attributes = fs.getAttributes(f);
+ if (attributes.isDirectory()) {
+ if (new File(f, Constants.DOT_GIT).exists())
+ mode = FileMode.GITLINK;
else
- mode = FileMode.REGULAR_FILE;
- } catch (IOException e) {
- mode = FileMode.MISSING;
- }
- this.mode = mode;
+ mode = FileMode.TREE;
+ } else if (attributes.isExecutable())
+ mode = FileMode.EXECUTABLE_FILE;
+ else
+ mode = FileMode.REGULAR_FILE;
}
@Override
@Override
public String getName() {
- return file.getName();
+ return attributes.getName();
}
@Override
public long getLength() {
- if (length < 0) {
- try {
- length = fs.length(file);
- } catch (IOException e) {
- length = 0;
- }
- }
- return length;
+ return attributes.getLength();
}
@Override
public long getLastModified() {
- if (lastModified == 0) {
- try {
- lastModified = fs.lastModified(file);
- } catch (IOException e) {
- lastModified = 0;
- }
- }
- return lastModified;
+ return attributes.getLastModifiedTime();
}
@Override
public InputStream openInputStream() throws IOException {
- if (fs.isSymLink(file))
- return new ByteArrayInputStream(fs.readSymLink(file).getBytes(
+ if (fs.isSymLink(getFile()))
+ return new ByteArrayInputStream(fs.readSymLink(getFile())
+ .getBytes(
Constants.CHARACTER_ENCODING));
else
- return new FileInputStream(file);
+ return new FileInputStream(getFile());
}
/**
* @return the underlying file of this entry
*/
public File getFile() {
- return file;
+ return attributes.getFile();
}
}
this.value = value;
}
}
+
+ /**
+ * File attributes we typically care for.
+ *
+ * @since 3.3
+ */
+ public static class Attributes {
+
+ /**
+ * @return true if this are the attributes of a directory
+ */
+ public boolean isDirectory() {
+ return isDirectory;
+ }
+
+ /**
+ * @return true if this are the attributes of an executable file
+ */
+ public boolean isExecutable() {
+ return isExecutable;
+ }
+
+ /**
+ * @return true if this are the attributes of a symbolic link
+ */
+ public boolean isSymbolicLink() {
+ return isSymbolicLink;
+ }
+
+ /**
+ * @return true if this are the attributes of a regular file
+ */
+ public boolean isRegularFile() {
+ return isRegularFile;
+ }
+
+ /**
+ * @return the time when the file was created
+ */
+ public long getCreationTime() {
+ return creationTime;
+ }
+
+ /**
+ * @return the time (milliseconds since 1970-01-01) when this object was
+ * last modified
+ */
+ public long getLastModifiedTime() {
+ return lastModifiedTime;
+ }
+
+ private boolean isDirectory;
+
+ private boolean isSymbolicLink;
+
+ private boolean isRegularFile;
+
+ private long creationTime;
+
+ private long lastModifiedTime;
+
+ private boolean isExecutable;
+
+ private File file;
+
+ private boolean exists;
+
+ /**
+ * file length
+ */
+ protected long length = -1;
+
+ FS fs;
+
+ Attributes(FS fs, File file, boolean exists, boolean isDirectory,
+ boolean isExecutable, boolean isSymbolicLink,
+ boolean isRegularFile, long creationTime,
+ long lastModifiedTime, long length) {
+ this.fs = fs;
+ this.file = file;
+ this.exists = exists;
+ this.isDirectory = isDirectory;
+ this.isExecutable = isExecutable;
+ this.isSymbolicLink = isSymbolicLink;
+ this.isRegularFile = isRegularFile;
+ this.creationTime = creationTime;
+ this.lastModifiedTime = lastModifiedTime;
+ this.length = length;
+ }
+
+ /**
+ * Constructor when there are issues with reading
+ *
+ * @param fs
+ * @param path
+ */
+ public Attributes(File path, FS fs) {
+ this.file = path;
+ this.fs = fs;
+ }
+
+ /**
+ * @return length of this file object
+ */
+ public long getLength() {
+ if (length == -1)
+ return length = file.length();
+ return length;
+ }
+
+ /**
+ * @return the filename
+ */
+ public String getName() {
+ return file.getName();
+ }
+
+ /**
+ * @return the file the attributes apply to
+ */
+ public File getFile() {
+ return file;
+ }
+
+ boolean exists() {
+ return exists;
+ }
+ }
+
+ /**
+ * @param path
+ * @return the file attributes we care for
+ * @since 3.3
+ */
+ public Attributes getAttributes(File path) {
+ boolean isDirectory = isDirectory(path);
+ boolean isFile = !isDirectory && path.isFile();
+ assert path.exists() == isDirectory || isFile;
+ boolean exists = isDirectory || isFile;
+ boolean canExecute = exists && !isDirectory && canExecute(path);
+ boolean isSymlink = false;
+ long lastModified = exists ? path.lastModified() : 0L;
+ long createTime = 0L;
+ return new Attributes(this, path, exists, isDirectory, canExecute,
+ isSymlink, isFile, createTime, lastModified, -1);
+ }
}