@ -45,6 +45,7 @@ package org.eclipse.jgit.internal.storage.file;
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 ;
@ -69,6 +70,13 @@ import org.eclipse.jgit.util.FS;
* 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 >
@ -76,7 +84,7 @@ public class FileSnapshot {
* 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 .
@ -85,7 +93,7 @@ public class FileSnapshot {
* 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 ) ;
@ -105,12 +113,16 @@ public class FileSnapshot {
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 ) ;
}
}
/ * *
/ * *
@ -126,7 +138,7 @@ public class FileSnapshot {
* /
* /
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. */
@ -138,10 +150,16 @@ public class FileSnapshot {
/** 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 ;
}
}
/ * *
/ * *
@ -151,6 +169,13 @@ public class FileSnapshot {
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 .
*
*
@ -160,12 +185,16 @@ public class FileSnapshot {
* /
* /
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 ) ;
}
}
/ * *
/ * *