Commit 53c0bd81a2915d6f82ef2f9c0703770783a3dc89

Marc Pegon 2011-05-27T22:37:10

Added error for ambiguous oid prefixes. Added methods to compare the first nth hexadecimal characters (i.e. packets of 4 bits) of OIDs.

diff --git a/include/git2/errors.h b/include/git2/errors.h
index 7e957b8..3ed5cd6 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -119,6 +119,9 @@ typedef enum {
 
 	/** The specified object has its data corrupted */
 	GIT_EOBJCORRUPTED = -28,
+
+	/** The given short oid is ambiguous */
+	GIT_EAMBIGUOUSOIDPREFIX = -29,
 } git_error;
 
 /**
diff --git a/include/git2/oid.h b/include/git2/oid.h
index 4538c61..e8803ce 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -133,6 +133,16 @@ GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src);
 GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);
 
 /**
+ * Compare the first 'len' hexadecimal characters (packets of 4 bits)
+ * of two oid structures.
+ * @param len the number of hex chars to compare
+ * @param a first oid structure.
+ * @param b second oid structure.
+ * @return 1 in case of a match
+ */
+GIT_EXTERN(int) gid_oid_match(unsigned int len, git_oid *a, git_oid *b);
+
+/**
  * OID Shortener object
  */
 typedef struct git_oid_shorten git_oid_shorten;
diff --git a/src/cache.h b/src/cache.h
index 4794dea..3038030 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -42,6 +42,11 @@ GIT_INLINE(int) git_cached_obj_compare(git_cached_obj *obj, const git_oid *oid)
 	return git_oid_cmp(&obj->oid, oid);
 }
 
+GIT_INLINE(int) git_cached_obj_match(unsigned int len, git_cached_obj *obj, const git_oid *oid)
+{
+	return git_oid_match(len, &obj->oid, oid);
+}
+
 GIT_INLINE(void) git_cached_obj_incref(git_cached_obj *obj)
 {
 	git_atomic_inc(&obj->refcount);
diff --git a/src/errors.c b/src/errors.c
index 1fb68ee..7da02b4 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -61,6 +61,7 @@ static struct {
 	{GIT_EEXISTS, "A reference with this name already exists"},
 	{GIT_EOVERFLOW, "The given integer literal is too large to be parsed"},
 	{GIT_ENOTNUM, "The given literal is not a valid number"},
+	{GIT_EAMBIGUOUSOIDPREFIX, "The given oid prefix is ambiguous"},
 };
 
 const char *git_strerror(int num)
diff --git a/src/oid.c b/src/oid.c
index 5c5238b..f743da8 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -173,6 +173,26 @@ int git_oid_cmp(const git_oid *a, const git_oid *b)
 }
 
 
+int git_oid_match_raw(unsigned int len, const unsigned char *a, const unsigned char *b)
+{
+        do {
+                if (*a != *b)
+                        return 0;
+                a++;
+                b++;
+                len -= 2;
+        } while (len > 1);
+        if (len)
+                if ((*a ^ *b) & 0xf0)
+                        return 0;
+        return 1;
+}
+
+int gid_oid_match(unsigned int len, git_oid *a, git_oid *b)
+{
+	return git_oid_match_raw(len, a->id, b->id);
+}
+
 typedef short node_index;
 
 typedef union {
diff --git a/src/oid.h b/src/oid.h
new file mode 100644
index 0000000..79f5b65
--- /dev/null
+++ b/src/oid.h
@@ -0,0 +1,7 @@
+#ifndef INCLUDE_oid_h__
+#define INCLUDE_oid_h__
+
+/* This can be useful for internal use */
+int git_oid_match_raw(unsigned int len, const unsigned char *a, const unsigned char *b);
+
+#endif