diff options
author | Chris Aniszczyk <caniszczyk@gmail.com> | 2010-11-13 12:31:02 -0500 |
---|---|---|
committer | Code Review <codereview-daemon@eclipse.org> | 2010-11-13 12:31:02 -0500 |
commit | 56a802104a0abb7aebcb3ff052556c66f1cc0a37 (patch) | |
tree | cf7c2e3f24053baa34d72f5befba1131ad997b4c /org.eclipse.jgit | |
parent | 43156bf0451cb108ce72d27543f9de197590861d (diff) | |
parent | faa0747cce9826137b3841661a5b745030fb55fe (diff) | |
download | jgit-56a802104a0abb7aebcb3ff052556c66f1cc0a37.tar.gz jgit-56a802104a0abb7aebcb3ff052556c66f1cc0a37.zip |
Merge "Add in-memory updating support to NoteMap"
Diffstat (limited to 'org.eclipse.jgit')
4 files changed, 172 insertions, 0 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java index 85337c8d15..760528618c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java @@ -84,6 +84,9 @@ class FanoutBucket extends InMemoryNoteBucket { */ private final NoteBucket[] table; + /** Number of non-null slots in {@link #table}. */ + private int cnt; + FanoutBucket(int prefixLen) { super(prefixLen); table = new NoteBucket[256]; @@ -91,6 +94,7 @@ class FanoutBucket extends InMemoryNoteBucket { void parseOneEntry(int cell, ObjectId id) { table[cell] = new LazyNoteBucket(id); + cnt++; } @Override @@ -99,6 +103,39 @@ class FanoutBucket extends InMemoryNoteBucket { return b != null ? b.get(objId, or) : null; } + @Override + InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, + ObjectReader or) throws IOException { + int cell = cell(noteOn); + NoteBucket b = table[cell]; + + if (b == null) { + if (noteData == null) + return this; + + LeafBucket n = new LeafBucket(prefixLen + 2); + table[cell] = n.set(noteOn, noteData, or); + cnt++; + return this; + + } else { + NoteBucket n = b.set(noteOn, noteData, or); + if (n == null) { + table[cell] = null; + cnt--; + + if (cnt == 0) + return null; + + return this; + + } else if (n != b) { + table[cell] = n; + } + return this; + } + } + private int cell(AnyObjectId id) { return id.getByte(prefixLen >> 1); } @@ -115,6 +152,12 @@ class FanoutBucket extends InMemoryNoteBucket { return load(objId, or).get(objId, or); } + @Override + InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, + ObjectReader or) throws IOException { + return load(noteOn, or).set(noteOn, noteData, or); + } + private NoteBucket load(AnyObjectId objId, ObjectReader or) throws IOException { AbbreviatedObjectId p = objId.abbreviate(prefixLen + 2); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java index 66d773a05d..ce4feae259 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java @@ -43,6 +43,8 @@ package org.eclipse.jgit.notes; +import java.io.IOException; + import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; @@ -96,6 +98,34 @@ class LeafBucket extends InMemoryNoteBucket { return 0 <= idx ? notes[idx].getData() : null; } + InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, + ObjectReader or) throws IOException { + int p = search(noteOn); + if (0 <= p) { + if (noteData != null) { + notes[p].setData(noteData.copy()); + return this; + + } else { + System.arraycopy(notes, p + 1, notes, p, cnt - p - 1); + cnt--; + return 0 < cnt ? this : null; + } + + } else if (noteData != null) { + growIfFull(); + p = -(p + 1); + if (p < cnt) + System.arraycopy(notes, p, notes, p + 1, cnt - p); + notes[p] = new Note(noteOn, noteData.copy()); + cnt++; + return this; + + } else { + return this; + } + } + void parseOneEntry(AnyObjectId noteOn, AnyObjectId noteData) { growIfFull(); notes[cnt++] = new Note(noteOn, noteData.copy()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java index 286f140847..f75fc1f942 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java @@ -58,4 +58,7 @@ import org.eclipse.jgit.lib.ObjectReader; abstract class NoteBucket { abstract ObjectId get(AnyObjectId objId, ObjectReader reader) throws IOException; + + abstract InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, + ObjectReader reader) throws IOException; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java index d2f07279e1..88ab481794 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java @@ -51,7 +51,9 @@ import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; @@ -66,6 +68,17 @@ import org.eclipse.jgit.revwalk.RevTree; */ public class NoteMap { /** + * Construct a new empty note map. + * + * @return an empty note map. + */ + public static NoteMap newEmptyMap() { + NoteMap r = new NoteMap(null /* no reader */); + r.root = new LeafBucket(0); + return r; + } + + /** * Load a collection of notes from a branch. * * @param reader @@ -213,6 +226,89 @@ public class NoteMap { return null; } + /** + * Attach (or remove) a note on an object. + * + * If no note exists, a new note is stored. If a note already exists for the + * given object, it is replaced (or removed). + * + * This method only updates the map in memory. + * + * If the caller wants to attach a UTF-8 encoded string message to an + * object, {@link #set(AnyObjectId, String, ObjectInserter)} is a convenient + * way to encode and update a note in one step. + * + * @param noteOn + * the object to attach the note to. This same ObjectId can later + * be used as an argument to {@link #get(AnyObjectId)} or + * {@link #getCachedBytes(AnyObjectId, int)} to read back the + * {@code noteData}. + * @param noteData + * data to associate with the note. This must be the ObjectId of + * a blob that already exists in the repository. If null the note + * will be deleted, if present. + * @throws IOException + * a portion of the note space is not accessible. + */ + public void set(AnyObjectId noteOn, ObjectId noteData) throws IOException { + InMemoryNoteBucket newRoot = root.set(noteOn, noteData, reader); + if (newRoot == null) { + newRoot = new LeafBucket(0); + newRoot.nonNotes = root.nonNotes; + } + root = newRoot; + } + + /** + * Attach a note to an object. + * + * If no note exists, a new note is stored. If a note already exists for the + * given object, it is replaced (or removed). + * + * @param noteOn + * the object to attach the note to. This same ObjectId can later + * be used as an argument to {@link #get(AnyObjectId)} or + * {@link #getCachedBytes(AnyObjectId, int)} to read back the + * {@code noteData}. + * @param noteData + * text to store in the note. The text will be UTF-8 encoded when + * stored in the repository. If null the note will be deleted, if + * the empty string a note with the empty string will be stored. + * @param ins + * inserter to write the encoded {@code noteData} out as a blob. + * The caller must ensure the inserter is flushed before the + * updated note map is made available for reading. + * @throws IOException + * the note data could not be stored in the repository. + */ + public void set(AnyObjectId noteOn, String noteData, ObjectInserter ins) + throws IOException { + ObjectId dataId; + if (noteData != null) { + byte[] dataUTF8 = Constants.encode(noteData); + dataId = ins.insert(Constants.OBJ_BLOB, dataUTF8); + } else { + dataId = null; + } + set(noteOn, dataId); + } + + /** + * Remove a note from an object. + * + * If no note exists, no action is performed. + * + * This method only updates the map in memory. + * + * @param noteOn + * the object to remove the note from. + * @throws IOException + * a portion of the note space is not accessible. + */ + public void remove(AnyObjectId noteOn) throws IOException { + set(noteOn, null); + } + private void load(ObjectId rootTree) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { AbbreviatedObjectId none = AbbreviatedObjectId.fromString(""); |