aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorChris Aniszczyk <caniszczyk@gmail.com>2010-11-13 12:31:02 -0500
committerCode Review <codereview-daemon@eclipse.org>2010-11-13 12:31:02 -0500
commit56a802104a0abb7aebcb3ff052556c66f1cc0a37 (patch)
treecf7c2e3f24053baa34d72f5befba1131ad997b4c /org.eclipse.jgit
parent43156bf0451cb108ce72d27543f9de197590861d (diff)
parentfaa0747cce9826137b3841661a5b745030fb55fe (diff)
downloadjgit-56a802104a0abb7aebcb3ff052556c66f1cc0a37.tar.gz
jgit-56a802104a0abb7aebcb3ff052556c66f1cc0a37.zip
Merge "Add in-memory updating support to NoteMap"
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMap.java96
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("");