|
|
|
@ -52,19 +52,13 @@ import java.io.FileOutputStream;
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.io.InputStreamReader; |
|
|
|
|
import java.io.Reader; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.TreeSet; |
|
|
|
|
|
|
|
|
|
import org.eclipse.jgit.dircache.DirCache; |
|
|
|
|
import org.eclipse.jgit.dircache.DirCacheIterator; |
|
|
|
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException; |
|
|
|
|
import org.eclipse.jgit.errors.MissingObjectException; |
|
|
|
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
|
|
|
|
import org.eclipse.jgit.storage.file.FileRepository; |
|
|
|
|
import org.eclipse.jgit.treewalk.FileTreeIteratorWithTimeControl; |
|
|
|
|
import org.eclipse.jgit.treewalk.NameConflictTreeWalk; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -126,45 +120,85 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
|
|
|
|
|
trash = db.getWorkTree(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String indexState(TreeSet<Long> modTimes) |
|
|
|
|
throws IllegalStateException, MissingObjectException, |
|
|
|
|
IncorrectObjectTypeException, IOException { |
|
|
|
|
public static final int MOD_TIME = 1; |
|
|
|
|
|
|
|
|
|
public static final int SMUDGE = 2; |
|
|
|
|
|
|
|
|
|
public static final int LENGTH = 4; |
|
|
|
|
|
|
|
|
|
public static final int CONTENT_ID = 8; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Represent the state of the index in one String. This representation is |
|
|
|
|
* useful when writing tests which do assertions on the state of the index. |
|
|
|
|
* By default information about path, mode, stage (if different from 0) is |
|
|
|
|
* included. A bitmask controls which additional info about |
|
|
|
|
* modificationTimes, smudge state and length is included. |
|
|
|
|
* <p> |
|
|
|
|
* The format of the returned string is described with this BNF: |
|
|
|
|
* |
|
|
|
|
* <pre> |
|
|
|
|
* result = ( "[" path mode stage? time? smudge? length? sha1? "]" )* . |
|
|
|
|
* mode = ", mode:" number . |
|
|
|
|
* stage = ", stage:" number . |
|
|
|
|
* time = ", time:t" timestamp-index . |
|
|
|
|
* smudge = "" | ", smudged" . |
|
|
|
|
* length = ", length:" number . |
|
|
|
|
* sha1 = ", sha1:" hex-sha1 . |
|
|
|
|
* |
|
|
|
|
* 'stage' is only presented when the stage is different from 0. All |
|
|
|
|
* reported time stamps are mapped to strings like "t0", "t1", ... "tn". The |
|
|
|
|
* smallest reported time-stamp will be called "t0". This allows to write |
|
|
|
|
* assertions against the string although the concrete value of the |
|
|
|
|
* time stamps is unknown. |
|
|
|
|
* |
|
|
|
|
* @param includedOptions |
|
|
|
|
* a bitmask constructed out of the constants {@link #MOD_TIME}, |
|
|
|
|
* {@link #SMUDGE}, {@link #LENGTH} and {@link #CONTENT_ID} |
|
|
|
|
* controlling which info is present in the resulting string. |
|
|
|
|
* @return a string encoding the index state |
|
|
|
|
* @throws IllegalStateException |
|
|
|
|
* @throws IOException |
|
|
|
|
*/ |
|
|
|
|
public String indexState(int includedOptions) |
|
|
|
|
throws IllegalStateException, IOException { |
|
|
|
|
DirCache dc = db.readDirCache(); |
|
|
|
|
Map lookup = new HashMap(); |
|
|
|
|
List ret = new ArrayList(dc.getEntryCount()); |
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
TreeSet<Long> timeStamps = null; |
|
|
|
|
|
|
|
|
|
// iterate once over the dircache just to collect all time stamps
|
|
|
|
|
if (0 != (includedOptions & MOD_TIME)) { |
|
|
|
|
timeStamps = new TreeSet<Long>(); |
|
|
|
|
for (int i=0; i<dc.getEntryCount(); ++i) |
|
|
|
|
timeStamps.add(Long.valueOf(dc.getEntry(i).getLastModified())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// iterate again, now produce the result string
|
|
|
|
|
NameConflictTreeWalk tw = new NameConflictTreeWalk(db); |
|
|
|
|
tw.reset(); |
|
|
|
|
tw.addTree(new FileTreeIteratorWithTimeControl(db, modTimes)); |
|
|
|
|
tw.addTree(new DirCacheIterator(dc)); |
|
|
|
|
boolean smudgedBefore; |
|
|
|
|
while (tw.next()) { |
|
|
|
|
List entry = new ArrayList(4); |
|
|
|
|
FileTreeIteratorWithTimeControl fIt = tw.getTree(0, |
|
|
|
|
FileTreeIteratorWithTimeControl.class); |
|
|
|
|
DirCacheIterator dcIt = tw.getTree(1, DirCacheIterator.class); |
|
|
|
|
entry.add(tw.getPathString()); |
|
|
|
|
entry.add("modTime(index/file): " |
|
|
|
|
+ ((dcIt == null) ? "null" : lookup(Long.valueOf(dcIt |
|
|
|
|
.getDirCacheEntry().getLastModified()), "t%n", |
|
|
|
|
lookup)) |
|
|
|
|
+ "/" |
|
|
|
|
+ ((fIt == null) ? "null" : lookup( |
|
|
|
|
Long.valueOf(fIt.getEntryLastModified()), "t%n", |
|
|
|
|
lookup))); |
|
|
|
|
smudgedBefore = (dcIt == null) ? false : dcIt.getDirCacheEntry() |
|
|
|
|
.isSmudged(); |
|
|
|
|
if (fIt != null |
|
|
|
|
&& dcIt != null |
|
|
|
|
&& fIt.isModified(dcIt.getDirCacheEntry(), true, true, |
|
|
|
|
db.getFS())) |
|
|
|
|
entry.add("dirty"); |
|
|
|
|
if (dcIt != null && dcIt.getDirCacheEntry().isSmudged()) |
|
|
|
|
entry.add("smudged"); |
|
|
|
|
else if (smudgedBefore) |
|
|
|
|
entry.add("unsmudged"); |
|
|
|
|
ret.add(entry); |
|
|
|
|
DirCacheIterator dcIt = tw.getTree(0, DirCacheIterator.class); |
|
|
|
|
sb.append("["+tw.getPathString()+", mode:" + dcIt.getEntryFileMode()); |
|
|
|
|
int stage = dcIt.getDirCacheEntry().getStage(); |
|
|
|
|
if (stage != 0) |
|
|
|
|
sb.append(", stage:" + stage); |
|
|
|
|
if (0 != (includedOptions & MOD_TIME)) { |
|
|
|
|
sb.append(", time:t"+ |
|
|
|
|
timeStamps.headSet(Long.valueOf(dcIt.getDirCacheEntry().getLastModified())).size()); |
|
|
|
|
} |
|
|
|
|
if (0 != (includedOptions & SMUDGE)) |
|
|
|
|
if (dcIt.getDirCacheEntry().isSmudged()) |
|
|
|
|
sb.append(", smudged"); |
|
|
|
|
if (0 != (includedOptions & LENGTH)) |
|
|
|
|
sb.append(", length:" |
|
|
|
|
+ Integer.toString(dcIt.getDirCacheEntry().getLength())); |
|
|
|
|
if (0 != (includedOptions & CONTENT_ID)) |
|
|
|
|
sb.append(", sha1:" + ObjectId.toString(dcIt |
|
|
|
|
.getEntryObjectId())); |
|
|
|
|
sb.append("]"); |
|
|
|
|
} |
|
|
|
|
return ret.toString(); |
|
|
|
|
return sb.toString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -186,7 +220,7 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
|
|
|
|
|
* @param lookupTable |
|
|
|
|
* a table storing object-name mappings. |
|
|
|
|
* @return a name of that object. Is not guaranteed to be unique. Use |
|
|
|
|
* nameTemplates containing "%n" to always have uniqe names |
|
|
|
|
* nameTemplates containing "%n" to always have unique names |
|
|
|
|
*/ |
|
|
|
|
public static String lookup(Object l, String nameTemplate, |
|
|
|
|
Map<Object, String> lookupTable) { |
|
|
|
|