Merge "Add in-memory updating support to NoteMap"
This commit is contained in:
commit
56a802104a
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Copyright (C) 2010, Google Inc.
|
||||
* and other copyright owners as documented in the project's IP log.
|
||||
*
|
||||
* This program and the accompanying materials are made available
|
||||
* under the terms of the Eclipse Distribution License v1.0 which
|
||||
* accompanies this distribution, is reproduced below, and is
|
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.eclipse.jgit.notes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.MutableObjectId;
|
||||
|
||||
public class LeafBucketTest extends TestCase {
|
||||
public void testEmpty() {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
assertNull(b.get(id(0x00), null));
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertNull(b.get(id(0xfe), null));
|
||||
}
|
||||
|
||||
public void testParseFive() {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
b.parseOneEntry(id(0x11), id(0x81));
|
||||
b.parseOneEntry(id(0x22), id(0x82));
|
||||
b.parseOneEntry(id(0x33), id(0x83));
|
||||
b.parseOneEntry(id(0x44), id(0x84));
|
||||
b.parseOneEntry(id(0x55), id(0x85));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testSetFive_InOrder() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testSetFive_ReverseOrder() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testSetFive_MixedOrder() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testSet_Replace() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x01), null));
|
||||
assertEquals(id(0x01), b.get(id(0x11), null));
|
||||
}
|
||||
|
||||
public void testRemoveMissingNote() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
assertNull(b.get(id(0x11), null));
|
||||
assertSame(b, b.set(id(0x11), null, null));
|
||||
assertNull(b.get(id(0x11), null));
|
||||
}
|
||||
|
||||
public void testRemoveFirst() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
|
||||
assertSame(b, b.set(id(0x11), null, null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertNull(b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testRemoveMiddle() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
|
||||
assertSame(b, b.set(id(0x33), null, null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertNull(b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertEquals(id(0x85), b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testRemoveLast() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertSame(b, b.set(id(0x22), id(0x82), null));
|
||||
assertSame(b, b.set(id(0x33), id(0x83), null));
|
||||
assertSame(b, b.set(id(0x44), id(0x84), null));
|
||||
assertSame(b, b.set(id(0x55), id(0x85), null));
|
||||
|
||||
assertSame(b, b.set(id(0x55), null, null));
|
||||
|
||||
assertNull(b.get(id(0x01), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
assertEquals(id(0x82), b.get(id(0x22), null));
|
||||
assertEquals(id(0x83), b.get(id(0x33), null));
|
||||
assertEquals(id(0x84), b.get(id(0x44), null));
|
||||
assertNull(b.get(id(0x55), null));
|
||||
assertNull(b.get(id(0x66), null));
|
||||
}
|
||||
|
||||
public void testRemoveMakesEmpty() throws IOException {
|
||||
LeafBucket b = new LeafBucket(0);
|
||||
|
||||
assertSame(b, b.set(id(0x11), id(0x81), null));
|
||||
assertEquals(id(0x81), b.get(id(0x11), null));
|
||||
|
||||
assertNull(b.set(id(0x11), null, null));
|
||||
assertNull(b.get(id(0x11), null));
|
||||
}
|
||||
|
||||
private static AnyObjectId id(int first) {
|
||||
MutableObjectId id = new MutableObjectId();
|
||||
id.setByte(1, first);
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -44,6 +44,8 @@
|
|||
package org.eclipse.jgit.notes;
|
||||
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
import org.eclipse.jgit.lib.MutableObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.RepositoryTestCase;
|
||||
|
@ -56,17 +58,21 @@ public class NoteMapTest extends RepositoryTestCase {
|
|||
|
||||
private ObjectReader reader;
|
||||
|
||||
private ObjectInserter inserter;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
tr = new TestRepository<Repository>(db);
|
||||
reader = db.newObjectReader();
|
||||
inserter = db.newObjectInserter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
reader.release();
|
||||
inserter.release();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
@ -182,6 +188,99 @@ public void testGetCachedBytes() throws Exception {
|
|||
assertEquals(exp, RawParseUtils.decode(act));
|
||||
}
|
||||
|
||||
public void testCreateFromEmpty() throws Exception {
|
||||
RevBlob a = tr.blob("a");
|
||||
RevBlob b = tr.blob("b");
|
||||
RevBlob data1 = tr.blob("data1");
|
||||
RevBlob data2 = tr.blob("data2");
|
||||
|
||||
NoteMap map = NoteMap.newEmptyMap();
|
||||
assertFalse("no a", map.contains(a));
|
||||
assertFalse("no b", map.contains(b));
|
||||
|
||||
map.set(a, data1);
|
||||
map.set(b, data2);
|
||||
|
||||
assertEquals(data1, map.get(a));
|
||||
assertEquals(data2, map.get(b));
|
||||
|
||||
map.remove(a);
|
||||
map.remove(b);
|
||||
|
||||
assertFalse("no a", map.contains(a));
|
||||
assertFalse("no b", map.contains(b));
|
||||
|
||||
map.set(a, "data1", inserter);
|
||||
assertEquals(data1, map.get(a));
|
||||
|
||||
map.set(a, null, inserter);
|
||||
assertFalse("no a", map.contains(a));
|
||||
}
|
||||
|
||||
public void testEditFlat() throws Exception {
|
||||
RevBlob a = tr.blob("a");
|
||||
RevBlob b = tr.blob("b");
|
||||
RevBlob data1 = tr.blob("data1");
|
||||
RevBlob data2 = tr.blob("data2");
|
||||
|
||||
RevCommit r = tr.commit() //
|
||||
.add(a.name(), data1) //
|
||||
.add(b.name(), data2) //
|
||||
.create();
|
||||
tr.parseBody(r);
|
||||
|
||||
NoteMap map = NoteMap.read(reader, r);
|
||||
map.set(a, data2);
|
||||
map.set(b, null);
|
||||
map.set(data1, b);
|
||||
map.set(data2, null);
|
||||
|
||||
assertEquals(data2, map.get(a));
|
||||
assertEquals(b, map.get(data1));
|
||||
assertFalse("no b", map.contains(b));
|
||||
assertFalse("no data2", map.contains(data2));
|
||||
|
||||
MutableObjectId id = new MutableObjectId();
|
||||
for (int p = 42; p > 0; p--) {
|
||||
id.setByte(1, p);
|
||||
map.set(id, data1);
|
||||
}
|
||||
|
||||
for (int p = 42; p > 0; p--) {
|
||||
id.setByte(1, p);
|
||||
assertTrue("contains " + id, map.contains(id));
|
||||
}
|
||||
}
|
||||
|
||||
public void testEditFanout2_38() throws Exception {
|
||||
RevBlob a = tr.blob("a");
|
||||
RevBlob b = tr.blob("b");
|
||||
RevBlob data1 = tr.blob("data1");
|
||||
RevBlob data2 = tr.blob("data2");
|
||||
|
||||
RevCommit r = tr.commit() //
|
||||
.add(fanout(2, a.name()), data1) //
|
||||
.add(fanout(2, b.name()), data2) //
|
||||
.create();
|
||||
tr.parseBody(r);
|
||||
|
||||
NoteMap map = NoteMap.read(reader, r);
|
||||
map.set(a, data2);
|
||||
map.set(b, null);
|
||||
map.set(data1, b);
|
||||
map.set(data2, null);
|
||||
|
||||
assertEquals(data2, map.get(a));
|
||||
assertEquals(b, map.get(data1));
|
||||
assertFalse("no b", map.contains(b));
|
||||
assertFalse("no data2", map.contains(data2));
|
||||
|
||||
map.set(a, null);
|
||||
map.set(data1, null);
|
||||
assertFalse("no a", map.contains(a));
|
||||
assertFalse("no data1", map.contains(data1));
|
||||
}
|
||||
|
||||
private static String fanout(int prefix, String name) {
|
||||
StringBuilder r = new StringBuilder();
|
||||
int i = 0;
|
||||
|
|
|
@ -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 @@ ObjectId get(AnyObjectId objId, ObjectReader or) throws IOException {
|
|||
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 @@ ObjectId get(AnyObjectId objId, ObjectReader or) throws IOException {
|
|||
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);
|
||||
|
|
|
@ -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 @@ ObjectId get(AnyObjectId objId, ObjectReader or) {
|
|||
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());
|
||||
|
|
|
@ -58,4 +58,7 @@
|
|||
abstract class NoteBucket {
|
||||
abstract ObjectId get(AnyObjectId objId, ObjectReader reader)
|
||||
throws IOException;
|
||||
|
||||
abstract InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData,
|
||||
ObjectReader reader) throws IOException;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,9 @@
|
|||
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;
|
||||
|
@ -65,6 +67,17 @@
|
|||
* shared {@code ObjectReader} at the proper times.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -213,6 +226,89 @@ public byte[] getCachedBytes(AnyObjectId id, int sizeLimit)
|
|||
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("");
|
||||
|
|
Loading…
Reference in New Issue