Selaa lähdekoodia

Merge branch 'stable-4.8' into stable-4.9

* stable-4.8:
  Prepare 4.7.9-SNAPSHOT builds
  JGit v4.7.8.201903121755-r
  Prepare 4.5.7-SNAPSHOT builds
  JGit v4.5.6.201903121547-r
  Check for packfile validity and fd before reading
  Move throw of PackInvalidException outside the catch
  Use FileSnapshot to get lastModified on PackFile
  Include size when comparing FileSnapshot
  Do not reuse packfiles when changed on filesystem
  Silence API warnings for new API introduced for fixes

Change-Id: I9a47153831f8eb10d3cd91b4157cf45385e5b13a
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v4.9.9.201903122025-r
Matthias Sohn 5 vuotta sitten
vanhempi
commit
c452c007ce

+ 6
- 0
org.eclipse.jgit/.settings/.api_filters Näytä tiedosto

<message_argument value="createNewFileAtomic(File)"/> <message_argument value="createNewFileAtomic(File)"/>
</message_arguments> </message_arguments>
</filter> </filter>
<filter id="1142947843">
<message_arguments>
<message_argument value="4.5.6"/>
<message_argument value="fileAttributes(File)"/>
</message_arguments>
</filter>
</resource> </resource>
<resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS$LockToken"> <resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS$LockToken">
<filter id="1141899266"> <filter id="1141899266">

+ 37
- 8
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java Näytä tiedosto



import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
* file is less than 3 seconds ago. * file is less than 3 seconds ago.
*/ */
public class FileSnapshot { public class FileSnapshot {
/**
* An unknown file size.
*
* This value is used when a comparison needs to happen purely on the lastUpdate.
*/
public static final long UNKNOWN_SIZE = -1;

/** /**
* A FileSnapshot that is considered to always be modified. * A FileSnapshot that is considered to always be modified.
* <p> * <p>
* file, but only after {@link #isModified(File)} gets invoked. The returned * file, but only after {@link #isModified(File)} gets invoked. The returned
* snapshot contains only invalid status information. * snapshot contains only invalid status information.
*/ */
public static final FileSnapshot DIRTY = new FileSnapshot(-1, -1);
public static final FileSnapshot DIRTY = new FileSnapshot(-1, -1, UNKNOWN_SIZE);


/** /**
* A FileSnapshot that is clean if the file does not exist. * A FileSnapshot that is clean if the file does not exist.
* file to be clean. {@link #isModified(File)} will return false if the file * file to be clean. {@link #isModified(File)} will return false if the file
* path does not exist. * path does not exist.
*/ */
public static final FileSnapshot MISSING_FILE = new FileSnapshot(0, 0) {
public static final FileSnapshot MISSING_FILE = new FileSnapshot(0, 0, 0) {
@Override @Override
public boolean isModified(File path) { public boolean isModified(File path) {
return FS.DETECTED.exists(path); return FS.DETECTED.exists(path);
public static FileSnapshot save(File path) { public static FileSnapshot save(File path) {
long read = System.currentTimeMillis(); long read = System.currentTimeMillis();
long modified; long modified;
long size;
try { try {
modified = FS.DETECTED.lastModified(path);
BasicFileAttributes fileAttributes = FS.DETECTED.fileAttributes(path);
modified = fileAttributes.lastModifiedTime().toMillis();
size = fileAttributes.size();
} catch (IOException e) { } catch (IOException e) {
modified = path.lastModified(); modified = path.lastModified();
size = path.length();
} }
return new FileSnapshot(read, modified);
return new FileSnapshot(read, modified, size);
} }


/** /**
*/ */
public static FileSnapshot save(long modified) { public static FileSnapshot save(long modified) {
final long read = System.currentTimeMillis(); final long read = System.currentTimeMillis();
return new FileSnapshot(read, modified);
return new FileSnapshot(read, modified, -1);
} }


/** Last observed modification time of the path. */ /** Last observed modification time of the path. */
/** True once {@link #lastRead} is far later than {@link #lastModified}. */ /** True once {@link #lastRead} is far later than {@link #lastModified}. */
private boolean cannotBeRacilyClean; private boolean cannotBeRacilyClean;


private FileSnapshot(long read, long modified) {
/** Underlying file-system size in bytes.
*
* When set to {@link #UNKNOWN_SIZE} the size is not considered for modification checks. */
private final long size;

private FileSnapshot(long read, long modified, long size) {
this.lastRead = read; this.lastRead = read;
this.lastModified = modified; this.lastModified = modified;
this.cannotBeRacilyClean = notRacyClean(read); this.cannotBeRacilyClean = notRacyClean(read);
this.size = size;
} }


/** /**
return lastModified; return lastModified;
} }


/**
* @return file size in bytes of last snapshot update
*/
public long size() {
return size;
}

/** /**
* Check if the path may have been modified since the snapshot was saved. * Check if the path may have been modified since the snapshot was saved.
* *
*/ */
public boolean isModified(File path) { public boolean isModified(File path) {
long currLastModified; long currLastModified;
long currSize;
try { try {
currLastModified = FS.DETECTED.lastModified(path);
BasicFileAttributes fileAttributes = FS.DETECTED.fileAttributes(path);
currLastModified = fileAttributes.lastModifiedTime().toMillis();
currSize = fileAttributes.size();
} catch (IOException e) { } catch (IOException e) {
currLastModified = path.lastModified(); currLastModified = path.lastModified();
currSize = path.length();
} }
return isModified(currLastModified);
return (currSize != UNKNOWN_SIZE && currSize != size) || isModified(currLastModified);
} }


/** /**

+ 2
- 2
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java Näytä tiedosto

} }


final String packName = base + PACK.getExtension(); final String packName = base + PACK.getExtension();
final File packFile = new File(packDirectory, packName);
final PackFile oldPack = forReuse.remove(packName); final PackFile oldPack = forReuse.remove(packName);
if (oldPack != null) {
if (oldPack != null && oldPack.getFileSnapshot().isModified(packFile)) {
list.add(oldPack); list.add(oldPack);
continue; continue;
} }


final File packFile = new File(packDirectory, packName);
list.add(new PackFile(packFile, extensions)); list.add(new PackFile(packFile, extensions));
foundNew = true; foundNew = true;
} }

+ 25
- 3
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java Näytä tiedosto



int packLastModified; int packLastModified;


private FileSnapshot fileSnapshot;

private volatile boolean invalid; private volatile boolean invalid;


private boolean invalidBitmap; private boolean invalidBitmap;
*/ */
public PackFile(final File packFile, int extensions) { public PackFile(final File packFile, int extensions) {
this.packFile = packFile; this.packFile = packFile;
this.packLastModified = (int) (packFile.lastModified() >> 10);
this.fileSnapshot = FileSnapshot.save(packFile);
this.packLastModified = (int) (fileSnapshot.lastModified() >> 10);
this.extensions = extensions; this.extensions = extensions;


// Multiply by 31 here so we can more directly combine with another // Multiply by 31 here so we can more directly combine with another
return getReverseIdx().findObject(offset); return getReverseIdx().findObject(offset);
} }


/**
* Return the @{@link FileSnapshot} associated to the underlying packfile
* that has been used when the object was created.
*
* @return the packfile @{@link FileSnapshot} that the object is loaded from.
*/
FileSnapshot getFileSnapshot() {
return fileSnapshot;
}

private final byte[] decompress(final long position, final int sz, private final byte[] decompress(final long position, final int sz,
final WindowCursor curs) throws IOException, DataFormatException { final WindowCursor curs) throws IOException, DataFormatException {
byte[] dstbuf; byte[] dstbuf;
} }


private void doOpen() throws IOException { private void doOpen() throws IOException {
if (invalid) {
throw new PackInvalidException(packFile);
}
try { try {
if (invalid)
throw new PackInvalidException(packFile);
synchronized (readLock) { synchronized (readLock) {
fd = new RandomAccessFile(packFile, "r"); //$NON-NLS-1$ fd = new RandomAccessFile(packFile, "r"); //$NON-NLS-1$
length = fd.length(); length = fd.length();


ByteArrayWindow read(final long pos, int size) throws IOException { ByteArrayWindow read(final long pos, int size) throws IOException {
synchronized (readLock) { synchronized (readLock) {
if (invalid || fd == null) {
// Due to concurrency between a read and another packfile invalidation thread
// one thread could come up to this point and then fail with NPE.
// Detect the situation and throw a proper exception so that can be properly
// managed by the main packfile search loop and the Git client won't receive
// any failures.
throw new PackInvalidException(packFile);
}
if (length < pos + size) if (length < pos + size)
size = (int) (length - pos); size = (int) (length - pos);
final byte[] buf = new byte[size]; final byte[] buf = new byte[size];

+ 14
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java Näytä tiedosto

import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.text.MessageFormat; import java.text.MessageFormat;
*/ */
public abstract boolean retryFailedLockFileCommit(); public abstract boolean retryFailedLockFileCommit();


/**
* Return all the attributes of a file, without following symbolic links.
*
* @param file
* @return {@link BasicFileAttributes} of the file
* @throws IOException in case of any I/O errors accessing the file
*
* @since 4.5.6
*/
public BasicFileAttributes fileAttributes(File file) throws IOException {
return FileUtils.fileAttributes(file);
}

/** /**
* Determine the user's home directory (location where preferences are). * Determine the user's home directory (location where preferences are).
* *

+ 13
- 0
org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java Näytä tiedosto

.toMillis(); .toMillis();
} }


/**
* Return all the attributes of a file, without following symbolic links.
*
* @param file
* @return {@link BasicFileAttributes} of the file
* @throws IOException in case of any I/O errors accessing the file
*
* @since 4.5.6
*/
static BasicFileAttributes fileAttributes(File file) throws IOException {
return Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
}

/** /**
* @param file * @param file
* @param time * @param time

Loading…
Peruuta
Tallenna