Commit 91a3d81fcf77040d5c432c86b5d4aebbec565468

Stefan Sperling 2018-11-11T13:41:46

introduce got errors with custom messages; add one for ERR_NO_OBJ

diff --git a/include/got_error.h b/include/got_error.h
index 1a82e73..5e8cb64 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -123,6 +123,14 @@ static const struct got_error {
 const struct got_error *got_error(int);
 
 /*
+ * Get an error object from the above list, for a given error code.
+ * Use the specified error message instead of the default one.
+ * Caution: If the message buffer lives in dynamically allocated memory,
+ * then this memory likely won't be freed.
+ */
+const struct got_error *got_error_msg(int, const char *);
+
+/*
  * Get a statically allocated error object with code GOT_ERR_ERRNO
  * and an error message obtained from strerror(3).
  */
@@ -141,3 +149,12 @@ const struct got_error *got_error_set_errno(int);
  * with the error code provided in the second argument.
  */
 const struct got_error *got_ferror(FILE *, int);
+
+/*
+ * Obtain an error with code GOT_ERR_NO_OBJ and an error message which
+ * contains the specified object ID. The message buffer is statically
+ * allocated; future invocations of this function will overwrite the
+ * message set during earlier invocations.
+ */
+struct got_object_id; /* forward declaration */
+const struct got_error *got_error_no_obj(struct got_object_id *);
diff --git a/lib/commit_graph.c b/lib/commit_graph.c
index f663cec..e91da57 100644
--- a/lib/commit_graph.c
+++ b/lib/commit_graph.c
@@ -639,7 +639,7 @@ got_commit_graph_iter_start(struct got_commit_graph *graph,
 
 	start_node = got_object_idset_get(graph->node_ids, id);
 	if (start_node == NULL)
-		return got_error(GOT_ERR_NO_OBJ);
+		return got_error_no_obj(id);
 
 	err = got_object_open_as_commit(&commit, repo, &start_node->id);
 	if (err)
diff --git a/lib/error.c b/lib/error.c
index b12d036..7063a0b 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -14,12 +14,22 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/queue.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sha1.h>
+#include <zlib.h>
 
 #include "got_error.h"
+#include "got_object.h"
+
+#include "got_lib_delta.h"
+#include "got_lib_inflate.h"
+#include "got_lib_object.h"
+#include "got_lib_sha1.h"
 
 #ifndef nitems
 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
@@ -39,6 +49,23 @@ got_error(int code)
 }
 
 const struct got_error *
+got_error_msg(int code, const char *msg)
+{
+	static struct got_error err;
+	int i;
+
+	for (i = 0; i < nitems(got_errors); i++) {
+		if (code == got_errors[i].code) {
+			err.code = code;
+			err.msg = msg;
+			return (const struct got_error *)&err;
+		}
+	}
+
+	abort();
+}
+
+const struct got_error *
 got_error_from_errno()
 {
 	static struct got_error err;
@@ -62,3 +89,21 @@ got_ferror(FILE *f, int code)
 		return got_error_from_errno();
 	return got_error(code);
 }
+
+const struct got_error *
+got_error_no_obj(struct got_object_id *id)
+{
+	static char msg[sizeof("object   not found") +
+	    SHA1_DIGEST_STRING_LENGTH];
+	char id_str[SHA1_DIGEST_STRING_LENGTH];
+	int ret;
+
+	if (!got_sha1_digest_to_str(id->sha1, id_str, sizeof(id_str)))
+		return got_error(GOT_ERR_NO_OBJ);
+
+	ret = snprintf(msg, sizeof(msg), "object %s not found", id_str);
+	if (ret == -1 || ret >= sizeof(msg))
+		return got_error(GOT_ERR_NO_OBJ);
+
+	return got_error_msg(GOT_ERR_NO_OBJ, msg);
+}
diff --git a/lib/object.c b/lib/object.c
index abcc58c..97f5a2e 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -232,7 +232,7 @@ got_object_open(struct got_object **obj, struct got_repository *repo,
 	fd = open(path, O_RDONLY | O_NOFOLLOW, GOT_DEFAULT_FILE_MODE);
 	if (fd == -1) {
 		if (errno == ENOENT)
-			err = got_error(GOT_ERR_NO_OBJ);
+			err = got_error_no_obj(id);
 		else
 			err = got_error_from_errno();
 		goto done;
diff --git a/lib/repository.c b/lib/repository.c
index 42722b7..3becb1c 100644
--- a/lib/repository.c
+++ b/lib/repository.c
@@ -673,7 +673,7 @@ got_repo_search_packidx(struct got_packidx **packidx, int *idx,
 			goto done;
 	}
 
-	err = got_error(GOT_ERR_NO_OBJ);
+	err = got_error_no_obj(id);
 done:
 	free(path_packdir);
 	if (packdir && closedir(packdir) != 0 && err == 0)
diff --git a/regress/delta/Makefile b/regress/delta/Makefile
index f616387..6ac1f2f 100644
--- a/regress/delta/Makefile
+++ b/regress/delta/Makefile
@@ -1,7 +1,7 @@
 .PATH:${.CURDIR}/../../lib
 
 PROG = delta_test
-SRCS = delta.c error.c opentemp.c path.c inflate.c delta_test.c
+SRCS = delta.c error.c opentemp.c path.c inflate.c sha1.c delta_test.c
 
 CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
 LDADD = -lz