* [JGIT PATCH 0/3] Introduce AbbreviatedObjectId
@ 2008-12-10 23:18 Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 1/3] Define an abstraction for handling abbreviated SHA-1 strings Shawn O. Pearce
0 siblings, 1 reply; 4+ messages in thread
From: Shawn O. Pearce @ 2008-12-10 23:18 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
I'm using this new type to handle the "index" line of a git patch
file, where object ids are generally shorter than 40 characters
and thus aren't parsable by ObjectId.
Reading the short id is important because we can validate that a
patch applies correctly by computing the SHA-1 of the result and
testing it against the abbreviated id read in the "index" line.
If the base object SHA-1 matches the abbreviated line then the
result of applying the patch must also match; if it doesn't the
patch application logic is broken.
Shawn O. Pearce (3):
Define an abstraction for handling abbreviated SHA-1 strings
Add ObjectId.startsWith(AbbreviatedObjectId)
Change AnyObjectId.abbreviate() to return AbbreviatedObjectId
.../ui/internal/components/RefContentProposal.java | 2 +-
.../egit/ui/internal/fetch/FetchResultTable.java | 12 +-
.../egit/ui/internal/push/PushResultTable.java | 21 +-
.../src/org/spearce/jgit/pgm/Branch.java | 2 +-
.../src/org/spearce/jgit/pgm/Fetch.java | 8 +-
.../src/org/spearce/jgit/pgm/Push.java | 5 +-
.../spearce/jgit/lib/AbbreviatedObjectIdTest.java | 285 ++++++++++++++++++++
.../org/spearce/jgit/lib/AbbreviatedObjectId.java | 262 ++++++++++++++++++
.../src/org/spearce/jgit/lib/AnyObjectId.java | 39 +++-
9 files changed, 608 insertions(+), 28 deletions(-)
create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
^ permalink raw reply [flat|nested] 4+ messages in thread
* [JGIT PATCH 1/3] Define an abstraction for handling abbreviated SHA-1 strings
2008-12-10 23:18 [JGIT PATCH 0/3] Introduce AbbreviatedObjectId Shawn O. Pearce
@ 2008-12-10 23:18 ` Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 2/3] Add ObjectId.startsWith(AbbreviatedObjectId) Shawn O. Pearce
0 siblings, 1 reply; 4+ messages in thread
From: Shawn O. Pearce @ 2008-12-10 23:18 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
The AbbreviatedObjectId class parses an abbreviated SHA-1 string
into a binary format, permitting it to be more efficiently matched
against existing binary ObjectId fields.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../spearce/jgit/lib/AbbreviatedObjectIdTest.java | 227 ++++++++++++++++++++
.../org/spearce/jgit/lib/AbbreviatedObjectId.java | 205 ++++++++++++++++++
.../src/org/spearce/jgit/lib/AnyObjectId.java | 2 +-
3 files changed, 433 insertions(+), 1 deletions(-)
create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
new file mode 100644
index 0000000..f540f49
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2008, Google Inc.
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+import junit.framework.TestCase;
+
+public class AbbreviatedObjectIdTest extends TestCase {
+ public void testEmpty_FromByteArray() {
+ final AbbreviatedObjectId i;
+ i = AbbreviatedObjectId.fromString(new byte[] {}, 0, 0);
+ assertNotNull(i);
+ assertEquals(0, i.length());
+ assertFalse(i.isComplete());
+ assertEquals("", i.name());
+ }
+
+ public void testEmpty_FromString() {
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString("");
+ assertNotNull(i);
+ assertEquals(0, i.length());
+ assertFalse(i.isComplete());
+ assertEquals("", i.name());
+ }
+
+ public void testFull_FromByteArray() {
+ final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final byte[] b = Constants.encodeASCII(s);
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(b, 0,
+ b.length);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertTrue(i.isComplete());
+ assertEquals(s, i.name());
+
+ final ObjectId f = i.toObjectId();
+ assertNotNull(f);
+ assertEquals(ObjectId.fromString(s), f);
+ assertEquals(f.hashCode(), i.hashCode());
+ }
+
+ public void testFull_FromString() {
+ final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertTrue(i.isComplete());
+ assertEquals(s, i.name());
+
+ final ObjectId f = i.toObjectId();
+ assertNotNull(f);
+ assertEquals(ObjectId.fromString(s), f);
+ assertEquals(f.hashCode(), i.hashCode());
+ }
+
+ public void test1_FromString() {
+ final String s = "7";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test2_FromString() {
+ final String s = "7b";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test3_FromString() {
+ final String s = "7b6";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test4_FromString() {
+ final String s = "7b6e";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test5_FromString() {
+ final String s = "7b6e8";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test6_FromString() {
+ final String s = "7b6e80";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test7_FromString() {
+ final String s = "7b6e806";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test8_FromString() {
+ final String s = "7b6e8067";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test9_FromString() {
+ final String s = "7b6e8067e";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void test17_FromString() {
+ final String s = "7b6e8067ec96acef9";
+ final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s);
+ assertNotNull(i);
+ assertEquals(s.length(), i.length());
+ assertFalse(i.isComplete());
+ assertEquals(s, i.name());
+ assertNull(i.toObjectId());
+ }
+
+ public void testEquals_Short() {
+ final String s = "7b6e8067";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s);
+ final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(s);
+ assertNotSame(a, b);
+ assertTrue(a.hashCode() == b.hashCode());
+ assertTrue(a.equals(b));
+ assertTrue(b.equals(a));
+ }
+
+ public void testEquals_Full() {
+ final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s);
+ final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(s);
+ assertNotSame(a, b);
+ assertTrue(a.hashCode() == b.hashCode());
+ assertTrue(a.equals(b));
+ assertTrue(b.equals(a));
+ }
+
+ public void testNotEquals_SameLength() {
+ final String sa = "7b6e8067";
+ final String sb = "7b6e806e";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa);
+ final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(sb);
+ assertFalse(a.equals(b));
+ assertFalse(b.equals(a));
+ }
+
+ public void testNotEquals_DiffLength() {
+ final String sa = "7b6e8067abcd";
+ final String sb = "7b6e8067";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa);
+ final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(sb);
+ assertFalse(a.equals(b));
+ assertFalse(b.equals(a));
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
new file mode 100644
index 0000000..1a8d296
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008, Google Inc.
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A prefix abbreviation of an {@link ObjectId}.
+ * <p>
+ * Sometimes Git produces abbreviated SHA-1 strings, using sufficient leading
+ * digits from the ObjectId name to still be unique within the repository the
+ * string was generated from. These ids are likely to be unique for a useful
+ * period of time, especially if they contain at least 6-10 hex digits.
+ * <p>
+ * This class converts the hex string into a binary form, to make it more
+ * efficient for matching against an object.
+ */
+public class AbbreviatedObjectId {
+ /**
+ * Convert an AbbreviatedObjectId from hex characters (US-ASCII).
+ *
+ * @param buf
+ * the US-ASCII buffer to read from.
+ * @param offset
+ * position to read the first character from.
+ * @param end
+ * one past the last position to read (<code>end-offset</code> is
+ * the length of the string).
+ * @return the converted object id.
+ */
+ public static final AbbreviatedObjectId fromString(final byte[] buf,
+ final int offset, final int end) {
+ if (end - offset > AnyObjectId.STR_LEN)
+ throw new IllegalArgumentException("Invalid id");
+ return fromHexString(buf, offset, end);
+ }
+
+ /**
+ * Convert an AbbreviatedObjectId from hex characters.
+ *
+ * @param str
+ * the string to read from. Must be <= 40 characters.
+ * @return the converted object id.
+ */
+ public static final AbbreviatedObjectId fromString(final String str) {
+ if (str.length() > AnyObjectId.STR_LEN)
+ throw new IllegalArgumentException("Invalid id: " + str);
+ final byte[] b = Constants.encodeASCII(str);
+ return fromHexString(b, 0, b.length);
+ }
+
+ private static final AbbreviatedObjectId fromHexString(final byte[] bs,
+ int ptr, final int end) {
+ try {
+ final int a = hexUInt32(bs, ptr, end);
+ final int b = hexUInt32(bs, ptr + 8, end);
+ final int c = hexUInt32(bs, ptr + 16, end);
+ final int d = hexUInt32(bs, ptr + 24, end);
+ final int e = hexUInt32(bs, ptr + 32, end);
+ return new AbbreviatedObjectId(end - ptr, a, b, c, d, e);
+ } catch (ArrayIndexOutOfBoundsException e1) {
+ try {
+ final String str = new String(bs, ptr, end - ptr, "US-ASCII");
+ throw new IllegalArgumentException("Invalid id: " + str);
+ } catch (UnsupportedEncodingException e2) {
+ throw new IllegalArgumentException("Invalid id");
+ }
+ }
+ }
+
+ private static final int hexUInt32(final byte[] bs, int p, final int end) {
+ if (8 <= end - p)
+ return AnyObjectId.hexUInt32(bs, p);
+
+ int r = 0, n = 0;
+ while (n < 8 && p < end) {
+ final int v = AnyObjectId.fromhex[bs[p++]];
+ if (v < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ r <<= 4;
+ r |= v;
+ n++;
+ }
+ return r << (8 - n) * 4;
+ }
+
+ /** Number of half-bytes used by this id. */
+ final int nibbles;
+
+ final int w1;
+
+ final int w2;
+
+ final int w3;
+
+ final int w4;
+
+ final int w5;
+
+ private AbbreviatedObjectId(final int n, final int new_1, final int new_2,
+ final int new_3, final int new_4, final int new_5) {
+ nibbles = n;
+ w1 = new_1;
+ w2 = new_2;
+ w3 = new_3;
+ w4 = new_4;
+ w5 = new_5;
+ }
+
+ /** @return number of hex digits appearing in this id */
+ public int length() {
+ return nibbles;
+ }
+
+ /** @return true if this ObjectId is actually a complete id. */
+ public boolean isComplete() {
+ return length() == AnyObjectId.RAW_LEN * 2;
+ }
+
+ /** @return a complete ObjectId; null if {@link #isComplete()} is false */
+ public ObjectId toObjectId() {
+ return isComplete() ? new ObjectId(w1, w2, w3, w4, w5) : null;
+ }
+
+ @Override
+ public int hashCode() {
+ return w2;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o instanceof AbbreviatedObjectId) {
+ final AbbreviatedObjectId b = (AbbreviatedObjectId) o;
+ return nibbles == b.nibbles && w1 == b.w1 && w2 == b.w2
+ && w3 == b.w3 && w4 == b.w4 && w5 == b.w5;
+ }
+ return false;
+ }
+
+ /**
+ * @return string form of the abbreviation, in lower case hexadecimal.
+ */
+ public final String name() {
+ final char[] b = new char[AnyObjectId.STR_LEN];
+
+ AnyObjectId.formatHexChar(b, 0, w1);
+ if (nibbles <= 8)
+ return new String(b, 0, nibbles);
+
+ AnyObjectId.formatHexChar(b, 8, w2);
+ if (nibbles <= 16)
+ return new String(b, 0, nibbles);
+
+ AnyObjectId.formatHexChar(b, 16, w3);
+ if (nibbles <= 24)
+ return new String(b, 0, nibbles);
+
+ AnyObjectId.formatHexChar(b, 24, w4);
+ if (nibbles <= 32)
+ return new String(b, 0, nibbles);
+
+ AnyObjectId.formatHexChar(b, 32, w5);
+ return new String(b, 0, nibbles);
+ }
+
+ @Override
+ public String toString() {
+ return "AbbreviatedObjectId[" + name() + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
index a534202..e88e09d 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
@@ -396,7 +396,7 @@ private void toHexCharArray(final char[] dst) {
private static final char[] hexchar = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- private static void formatHexChar(final char[] dst, final int p, int w) {
+ static void formatHexChar(final char[] dst, final int p, int w) {
int o = p + 7;
while (o >= p && w != 0) {
dst[o--] = hexchar[w & 0xf];
--
1.6.1.rc2.299.gead4c
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [JGIT PATCH 2/3] Add ObjectId.startsWith(AbbreviatedObjectId)
2008-12-10 23:18 ` [JGIT PATCH 1/3] Define an abstraction for handling abbreviated SHA-1 strings Shawn O. Pearce
@ 2008-12-10 23:18 ` Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 3/3] Change AnyObjectId.abbreviate() to return AbbreviatedObjectId Shawn O. Pearce
0 siblings, 1 reply; 4+ messages in thread
From: Shawn O. Pearce @ 2008-12-10 23:18 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
This test can be useful to determine if the object id at least
begins with an abbreviated id.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../spearce/jgit/lib/AbbreviatedObjectIdTest.java | 58 ++++++++++++++++++++
.../org/spearce/jgit/lib/AbbreviatedObjectId.java | 57 +++++++++++++++++++
.../src/org/spearce/jgit/lib/AnyObjectId.java | 11 ++++
3 files changed, 126 insertions(+), 0 deletions(-)
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
index f540f49..3f82d50 100644
--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/AbbreviatedObjectIdTest.java
@@ -224,4 +224,62 @@ public void testNotEquals_DiffLength() {
assertFalse(a.equals(b));
assertFalse(b.equals(a));
}
+
+ public void testPrefixCompare_Full() {
+ final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s1);
+ final ObjectId i1 = ObjectId.fromString(s1);
+ assertEquals(0, a.prefixCompare(i1));
+ assertTrue(i1.startsWith(a));
+
+ final String s2 = "7b6e8067ec96acef9a4184b43210d583b6d2f99b";
+ final ObjectId i2 = ObjectId.fromString(s2);
+ assertTrue(a.prefixCompare(i2) < 0);
+ assertFalse(i2.startsWith(a));
+
+ final String s3 = "7b6e8067ec96acef9a4184b43210d583b6d2f999";
+ final ObjectId i3 = ObjectId.fromString(s3);
+ assertTrue(a.prefixCompare(i3) > 0);
+ assertFalse(i3.startsWith(a));
+ }
+
+ public void testPrefixCompare_1() {
+ final String sa = "7";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa);
+
+ final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final ObjectId i1 = ObjectId.fromString(s1);
+ assertEquals(0, a.prefixCompare(i1));
+ assertTrue(i1.startsWith(a));
+
+ final String s2 = "8b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final ObjectId i2 = ObjectId.fromString(s2);
+ assertTrue(a.prefixCompare(i2) < 0);
+ assertFalse(i2.startsWith(a));
+
+ final String s3 = "6b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final ObjectId i3 = ObjectId.fromString(s3);
+ assertTrue(a.prefixCompare(i3) > 0);
+ assertFalse(i3.startsWith(a));
+ }
+
+ public void testPrefixCompare_17() {
+ final String sa = "7b6e8067ec96acef9";
+ final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa);
+
+ final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a";
+ final ObjectId i1 = ObjectId.fromString(s1);
+ assertEquals(0, a.prefixCompare(i1));
+ assertTrue(i1.startsWith(a));
+
+ final String s2 = "7b6e8067eca6acef9a4184b43210d583b6d2f99a";
+ final ObjectId i2 = ObjectId.fromString(s2);
+ assertTrue(a.prefixCompare(i2) < 0);
+ assertFalse(i2.startsWith(a));
+
+ final String s3 = "7b6e8067ec86acef9a4184b43210d583b6d2f99a";
+ final ObjectId i3 = ObjectId.fromString(s3);
+ assertTrue(a.prefixCompare(i3) > 0);
+ assertFalse(i3.startsWith(a));
+ }
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
index 1a8d296..206cc2f 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
@@ -39,6 +39,8 @@
import java.io.UnsupportedEncodingException;
+import org.spearce.jgit.util.NB;
+
/**
* A prefix abbreviation of an {@link ObjectId}.
* <p>
@@ -119,6 +121,24 @@ private static final int hexUInt32(final byte[] bs, int p, final int end) {
return r << (8 - n) * 4;
}
+ static int mask(final int nibbles, final int word, final int v) {
+ final int b = (word - 1) * 8;
+ if (b + 8 <= nibbles) {
+ // We have all of the bits required for this word.
+ //
+ return v;
+ }
+
+ if (nibbles < b) {
+ // We have none of the bits required for this word.
+ //
+ return 0;
+ }
+
+ final int s = 32 - (nibbles - b) * 4;
+ return (v >>> s) << s;
+ }
+
/** Number of half-bytes used by this id. */
final int nibbles;
@@ -157,6 +177,43 @@ public ObjectId toObjectId() {
return isComplete() ? new ObjectId(w1, w2, w3, w4, w5) : null;
}
+ /**
+ * Compares this abbreviation to a full object id.
+ *
+ * @param other
+ * the other object id.
+ * @return <0 if this abbreviation names an object that is less than
+ * <code>other</code>; 0 if this abbreviation exactly matches the
+ * first {@link #length()} digits of <code>other.name()</code>;
+ * >0 if this abbreviation names an object that is after
+ * <code>other</code>.
+ */
+ public int prefixCompare(final AnyObjectId other) {
+ int cmp;
+
+ cmp = NB.compareUInt32(w1, mask(1, other.w1));
+ if (cmp != 0)
+ return cmp;
+
+ cmp = NB.compareUInt32(w2, mask(2, other.w2));
+ if (cmp != 0)
+ return cmp;
+
+ cmp = NB.compareUInt32(w3, mask(3, other.w3));
+ if (cmp != 0)
+ return cmp;
+
+ cmp = NB.compareUInt32(w4, mask(4, other.w4));
+ if (cmp != 0)
+ return cmp;
+
+ return NB.compareUInt32(w5, mask(5, other.w5));
+ }
+
+ private int mask(final int word, final int v) {
+ return mask(nibbles, word, v);
+ }
+
@Override
public int hashCode() {
return w2;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
index e88e09d..8872017 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
@@ -226,6 +226,17 @@ int compareTo(final int[] bs, final int p) {
return NB.compareUInt32(w5, bs[p + 4]);
}
+ /**
+ * Tests if this ObjectId starts with the given abbreviation.
+ *
+ * @param abbr
+ * the abbreviation.
+ * @return true if this ObjectId begins with the abbreviation; else false.
+ */
+ public boolean startsWith(final AbbreviatedObjectId abbr) {
+ return abbr.prefixCompare(this) == 0;
+ }
+
public int hashCode() {
return w2;
}
--
1.6.1.rc2.299.gead4c
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [JGIT PATCH 3/3] Change AnyObjectId.abbreviate() to return AbbreviatedObjectId
2008-12-10 23:18 ` [JGIT PATCH 2/3] Add ObjectId.startsWith(AbbreviatedObjectId) Shawn O. Pearce
@ 2008-12-10 23:18 ` Shawn O. Pearce
0 siblings, 0 replies; 4+ messages in thread
From: Shawn O. Pearce @ 2008-12-10 23:18 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
By returning our abstraction type we can reuse the logic inside
AbbreviatedObjectId to format the abbreviated string. A result
can also be used to test against another ObjectId.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../ui/internal/components/RefContentProposal.java | 2 +-
.../egit/ui/internal/fetch/FetchResultTable.java | 12 ++++----
.../egit/ui/internal/push/PushResultTable.java | 21 ++++++++-------
.../src/org/spearce/jgit/pgm/Branch.java | 2 +-
.../src/org/spearce/jgit/pgm/Fetch.java | 8 +++---
.../src/org/spearce/jgit/pgm/Push.java | 5 ++-
.../org/spearce/jgit/lib/AbbreviatedObjectId.java | 4 +-
.../src/org/spearce/jgit/lib/AnyObjectId.java | 26 +++++++++++++++++--
8 files changed, 51 insertions(+), 29 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RefContentProposal.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RefContentProposal.java
index 60abaf3..b63c428 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RefContentProposal.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RefContentProposal.java
@@ -111,7 +111,7 @@ public String getDescription() {
final StringBuilder sb = new StringBuilder();
sb.append(refName);
sb.append('\n');
- sb.append(objectId.abbreviate(db));
+ sb.append(objectId.abbreviate(db).name());
sb.append(" - ");
if (obj instanceof Commit) {
final Commit c = ((Commit) obj);
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/fetch/FetchResultTable.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/fetch/FetchResultTable.java
index 868ca94..f1169d1 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/fetch/FetchResultTable.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/fetch/FetchResultTable.java
@@ -137,15 +137,15 @@ else if (tru.getLocalName().startsWith(Constants.R_TAGS))
}
if (r == RefUpdate.Result.FORCED) {
- final String aOld = tru.getOldObjectId().abbreviate(db);
- final String aNew = tru.getNewObjectId().abbreviate(db);
- return aOld + "..." + aNew; //$NON-NLS-1$
+ final String o = tru.getOldObjectId().abbreviate(db).name();
+ final String n = tru.getNewObjectId().abbreviate(db).name();
+ return o + "..." + n; //$NON-NLS-1$
}
if (r == RefUpdate.Result.FAST_FORWARD) {
- final String aOld = tru.getOldObjectId().abbreviate(db);
- final String aNew = tru.getNewObjectId().abbreviate(db);
- return aOld + ".." + aNew; //$NON-NLS-1$
+ final String o = tru.getOldObjectId().abbreviate(db).name();
+ final String n = tru.getNewObjectId().abbreviate(db).name();
+ return o + ".." + n; //$NON-NLS-1$
}
if (r == RefUpdate.Result.REJECTED)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/push/PushResultTable.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/push/PushResultTable.java
index c5e476b..6f460dc 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/push/PushResultTable.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/push/PushResultTable.java
@@ -233,9 +233,9 @@ public String getText(Object element) {
return UIText.PushResultTable_statusOkNewBranch;
}
- return oldRef.getObjectId().abbreviate(localDb)
+ return oldRef.getObjectId().abbreviate(localDb).name()
+ (rru.isFastForward() ? ".." : "...")
- + rru.getNewObjectId().abbreviate(localDb);
+ + rru.getNewObjectId().abbreviate(localDb).name();
case UP_TO_DATE:
return UIText.PushResultTable_statusUpToDate;
case NON_EXISTING:
@@ -289,7 +289,7 @@ public String getToolTipText(Object element) {
case OK:
if (rru.isDelete())
return NLS.bind(UIText.PushResultTable_statusDetailDeleted,
- oldRef.getObjectId().abbreviate(localDb));
+ oldRef.getObjectId().abbreviate(localDb).name());
if (oldRef == null)
return null;
if (rru.isFastForward())
@@ -305,20 +305,21 @@ public String getToolTipText(Object element) {
return UIText.PushResultTable_statusDetailNonFastForward;
case REJECTED_REMOTE_CHANGED:
final Ref remoteRef = oldRef;
- final String currentValue;
+ final String curVal;
if (remoteRef == null)
- currentValue = UIText.PushResultTable_refNonExisting;
+ curVal = UIText.PushResultTable_refNonExisting;
else
- currentValue = remoteRef.getObjectId().abbreviate(localDb);
+ curVal = remoteRef.getObjectId().abbreviate(localDb).name();
+
final ObjectId expectedOldObjectId = rru
.getExpectedOldObjectId();
- final String expectedValue;
+ final String expVal;
if (expectedOldObjectId.equals(ObjectId.zeroId()))
- expectedValue = UIText.PushResultTable_refNonExisting;
+ expVal = UIText.PushResultTable_refNonExisting;
else
- expectedValue = expectedOldObjectId.abbreviate(localDb);
+ expVal = expectedOldObjectId.abbreviate(localDb).name();
return NLS.bind(UIText.PushResultTable_statusDetailChanged,
- currentValue, expectedValue);
+ curVal, expVal);
case REJECTED_OTHER_REASON:
return rru.getMessage();
default:
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java
index db0aab8..11002f0 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Branch.java
@@ -167,7 +167,7 @@ private void printHead(final String ref, final boolean isCurrent,
final int spaces = maxNameLength - ref.length() + 1;
out.print(String.format("%" + spaces + "s", ""));
final ObjectId objectId = refObj.getObjectId();
- out.print(objectId.abbreviate(db));
+ out.print(objectId.abbreviate(db).name());
out.print(' ');
out.print(rw.parseCommit(objectId).getShortMessage());
}
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
index ad7e08f..e9d3260 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
@@ -131,14 +131,14 @@ else if (u.getLocalName().startsWith(Constants.R_TAGS))
}
if (r == RefUpdate.Result.FORCED) {
- final String aOld = u.getOldObjectId().abbreviate(db);
- final String aNew = u.getNewObjectId().abbreviate(db);
+ final String aOld = u.getOldObjectId().abbreviate(db).name();
+ final String aNew = u.getNewObjectId().abbreviate(db).name();
return aOld + "..." + aNew;
}
if (r == RefUpdate.Result.FAST_FORWARD) {
- final String aOld = u.getOldObjectId().abbreviate(db);
- final String aNew = u.getNewObjectId().abbreviate(db);
+ final String aOld = u.getOldObjectId().abbreviate(db).name();
+ final String aNew = u.getNewObjectId().abbreviate(db).name();
return aOld + ".." + aNew;
}
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
index 53ad080..19d31a1 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
@@ -181,8 +181,9 @@ private void printRefUpdateResult(final URIish uri,
boolean fastForward = rru.isFastForward();
final char flag = fastForward ? ' ' : '+';
final String summary = oldRef.getObjectId().abbreviate(db)
+ .name()
+ (fastForward ? ".." : "...")
- + rru.getNewObjectId().abbreviate(db);
+ + rru.getNewObjectId().abbreviate(db).name();
final String message = fastForward ? null : "forced update";
printUpdateLine(flag, summary, srcRef, remoteName, message);
}
@@ -205,7 +206,7 @@ printUpdateLine('!', "[rejected]", srcRef, remoteName,
case REJECTED_REMOTE_CHANGED:
final String message = "remote ref object changed - is not expected one "
- + rru.getExpectedOldObjectId().abbreviate(db);
+ + rru.getExpectedOldObjectId().abbreviate(db).name();
printUpdateLine('!', "[rejected]", srcRef, remoteName, message);
break;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
index 206cc2f..33b62b9 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AbbreviatedObjectId.java
@@ -52,7 +52,7 @@
* This class converts the hex string into a binary form, to make it more
* efficient for matching against an object.
*/
-public class AbbreviatedObjectId {
+public final class AbbreviatedObjectId {
/**
* Convert an AbbreviatedObjectId from hex characters (US-ASCII).
*
@@ -152,7 +152,7 @@ static int mask(final int nibbles, final int word, final int v) {
final int w5;
- private AbbreviatedObjectId(final int n, final int new_1, final int new_2,
+ AbbreviatedObjectId(final int n, final int new_1, final int new_2,
final int new_3, final int new_4, final int new_5) {
nibbles = n;
w1 = new_1;
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
index 8872017..7d7d61b 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AnyObjectId.java
@@ -432,16 +432,36 @@ public final String name() {
/**
* Return unique abbreviation (prefix) of this object SHA-1.
* <p>
+ * This method is a utility for <code>abbreviate(repo, 8)</code>.
+ *
+ * @param repo
+ * repository for checking uniqueness within.
+ * @return SHA-1 abbreviation.
+ */
+ public AbbreviatedObjectId abbreviate(final Repository repo) {
+ return abbreviate(repo, 8);
+ }
+
+ /**
+ * Return unique abbreviation (prefix) of this object SHA-1.
+ * <p>
* Current implementation is not guaranteeing uniqueness, it just returns
* fixed-length prefix of SHA-1 string.
- *
+ *
* @param repo
* repository for checking uniqueness within.
+ * @param len
+ * minimum length of the abbreviated string.
* @return SHA-1 abbreviation.
*/
- public String abbreviate(final Repository repo) {
+ public AbbreviatedObjectId abbreviate(final Repository repo, final int len) {
// TODO implement checking for uniqueness
- return name().substring(0, 7);
+ final int a = AbbreviatedObjectId.mask(len, 1, w1);
+ final int b = AbbreviatedObjectId.mask(len, 2, w2);
+ final int c = AbbreviatedObjectId.mask(len, 3, w3);
+ final int d = AbbreviatedObjectId.mask(len, 4, w4);
+ final int e = AbbreviatedObjectId.mask(len, 5, w5);
+ return new AbbreviatedObjectId(len, a, b, c, d, e);
}
/**
--
1.6.1.rc2.299.gead4c
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-12-10 23:20 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-10 23:18 [JGIT PATCH 0/3] Introduce AbbreviatedObjectId Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 1/3] Define an abstraction for handling abbreviated SHA-1 strings Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 2/3] Add ObjectId.startsWith(AbbreviatedObjectId) Shawn O. Pearce
2008-12-10 23:18 ` [JGIT PATCH 3/3] Change AnyObjectId.abbreviate() to return AbbreviatedObjectId Shawn O. Pearce
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).