commit dd669d1824c1e2077bc147b91460ca4209621ced from: Stefan Sperling date: Mon Mar 11 09:49:08 2024 UTC read 'commit refname' pairs on stdin commit - c6d588b78684a2992b61c72b64f1bb3bab4b560c commit + dd669d1824c1e2077bc147b91460ca4209621ced blob - 4746965b3fd5d0df1e8a79c035b8b42c798b661e blob + cdc23983f6af5f4cf642e738040bcb424ce25a4b --- gotd/libexec/got-notify-email/got-notify-email.c +++ gotd/libexec/got-notify-email/got-notify-email.c @@ -14,12 +14,20 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include #include +#include #include +#include +#include +#include #include "got_error.h" #include "got_repository.h" +#include "got_object.h" +#include "got_reference.h" __dead static void @@ -33,7 +41,7 @@ usage(void) static int validate_email_addr(const char *addr) { - return 0; + return 1; } static char * @@ -43,20 +51,70 @@ set_default_fromaddr(void) } static const struct got_error * -notify(struct got_repository *repo, const char *fromaddr, +send_notifications(struct got_repository *repo, const char *fromaddr, const char *recipient, char *replytoaddr, int shortlog, int with_diff) { - return got_error(GOT_ERR_NOT_IMPL); + const struct got_error *err; + char *line = NULL, *space = NULL; + size_t linesize = 0; + ssize_t linelen; + struct got_object_id *id = NULL; + struct got_reference *ref = NULL; + const char *refname; + int have_line = 0; + + while ((linelen = getline(&line, &linesize, stdin)) != -1) { + have_line = 1; + + while (linelen > 0 && line[linelen - 1] == '\n') { + line[linelen - 1] = '\0'; + linelen--; + } + + space = strchr(line, ' '); + if (space == NULL) { + err = got_error_fmt(GOT_ERR_BAD_REF_NAME, + "no separator found between commit ID and " + "reference name: %s", line); + goto done; + } + + *space = '\0'; + + refname = space + 1; + err = got_ref_open(&ref, repo, refname, 0); + if (err) + goto done; + + err = got_object_resolve_id_str(&id, repo, line); + if (err) + goto done; + + free(id); + id = NULL; + got_ref_close(ref); + ref = NULL; + } + + if (!have_line) + err = got_error_fmt(GOT_ERR_EOF, + "reading 'commit reference-name' pairs from stdin"); +done: + free(line); + free(id); + if (ref) + got_ref_close(ref); + return err; } int main(int argc, char *argv[]) { - const struct got_error *error; + const struct got_error *error = NULL; struct got_repository *repo = NULL; int ch, *pack_fds = NULL; - char *repo_path = NULL, *fromaddr = NULL; + char *cwd = NULL, *repo_path = NULL, *fromaddr = NULL; char *recipient = NULL, *replytoaddr = NULL; int shortlog = 0, with_diff = 0; @@ -83,26 +141,32 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc != 2) + if (argc != 1) usage(); - recipient = argv[1]; - + recipient = argv[0]; if (!validate_email_addr(recipient)) goto done; if (fromaddr == NULL) fromaddr = set_default_fromaddr(); + if (repo_path == NULL) { + cwd = getcwd(NULL, 0); + if (cwd == NULL) + error = got_error_from_errno("getcwd"); + repo_path = cwd; + } error = got_repo_pack_fds_open(&pack_fds); if (error != NULL) goto done; + error = got_repo_open(&repo, repo_path, NULL, pack_fds); if (error) goto done; - error = notify(repo, fromaddr, recipient, replytoaddr, shortlog, - with_diff); + error = send_notifications(repo, fromaddr, recipient, replytoaddr, + shortlog, with_diff); done: if (pack_fds) { const struct got_error *pack_err = @@ -115,6 +179,7 @@ done: if (error == NULL) error = close_err; } + free(cwd); if (error) { fflush(stdout); fprintf(stderr, "%s: %s\n", getprogname(), error->msg);