Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple registries and repositories #248

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
registry: Create an abstraction for registries.
  • Loading branch information
nouwaarom committed Dec 28, 2021
commit ab36df6ef5af059bfcd1c320990db42eb6319794
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ MAKEFILES = $(wildcard deps/*/Makefile)

export CC

CFLAGS += -std=c99 -Ideps -Wall -Wno-unused-function -U__STRICT_ANSI__
CFLAGS += -std=c99 -Ideps -Wall -Werror=return--type -Wno-unused-function -U__STRICT_ANSI__

ifdef STATIC
CFLAGS += -DCURL_STATICLIB $(shell deps/curl/bin/curl-config --cflags)
131 changes: 131 additions & 0 deletions deps/wiki-registry/github-registry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// github-registry.c
//
// Copyright (c) 2020 Elbert van de Put
// Based on work by Stephen Mathieson
// MIT licensed
//
#include <string.h>
#include "github-registry.h"
#include "gumbo-text-content/gumbo-text-content.h"
#include "gumbo-get-element-by-id/get-element-by-id.h"
#include "gumbo-get-elements-by-tag-name/get-elements-by-tag-name.h"
#include "http-get/http-get.h"
#include <curl/curl.h>
#include "substr/substr.h"
#include "strdup/strdup.h"
#include "case/case.h"
#include "trim/trim.h"
#include "wiki-registry-internal.h"

/**
* Add `href` to the given `package`.
*/
static void add_package_href(wiki_package_ptr_t self) {
size_t len = strlen(self->repo) + 20; // https://github.com/ \0
self->href = malloc(len);
if (self->href)
sprintf(self->href, "https://github.com/%s", self->repo);
}

/**
* Parse the given wiki `li` into a package.
*/
static wiki_package_ptr_t parse_li(GumboNode *li) {
wiki_package_ptr_t self = wiki_package_new();
char *text = NULL;

if (!self) goto cleanup;

text = gumbo_text_content(li);
if (!text) goto cleanup;

// TODO support unicode dashes
char *tok = strstr(text, " - ");
if (!tok) goto cleanup;

int pos = tok - text;
self->repo = substr(text, 0, pos);
self->description = substr(text, pos + 3, -1);
if (!self->repo || !self->description) goto cleanup;
trim(self->description);
trim(self->repo);

add_package_href(self);

cleanup:
free(text);
return self;
}

/**
* Parse a list of packages from the given `html`
*/
list_t *wiki_registry_parse(const char *html) {
GumboOutput *output = gumbo_parse(html);
list_t *pkgs = list_new();

GumboNode *body = gumbo_get_element_by_id("wiki-body", output->root);
if (body) {
// grab all category `<h2 />`s
list_t *h2s = gumbo_get_elements_by_tag_name("h2", body);
list_node_t *heading_node;
list_iterator_t *heading_iterator = list_iterator_new(h2s, LIST_HEAD);
while ((heading_node = list_iterator_next(heading_iterator))) {
GumboNode *heading = (GumboNode *) heading_node->val;
char *category = gumbo_text_content(heading);
// die if we failed to parse a category, as it's
// almost certinaly a malloc error
if (!category) break;
trim(case_lower(category));
GumboVector *siblings = &heading->parent->v.element.children;
size_t pos = heading->index_within_parent;

// skip elements until the UL
// TODO: don't hardcode position here
// 2:
// 1 - whitespace
// 2 - actual node
GumboNode *ul = siblings->data[pos + 2];
if (GUMBO_TAG_UL != ul->v.element.tag) {
free(category);
continue;
}

list_t *lis = gumbo_get_elements_by_tag_name("li", ul);
list_iterator_t *li_iterator = list_iterator_new(lis, LIST_HEAD);
list_node_t *li_node;
while ((li_node = list_iterator_next(li_iterator))) {
wiki_package_ptr_t package = parse_li(li_node->val);
if (package && package->description) {
package->category = strdup(category);
list_rpush(pkgs, list_node_new(package));
} else {
// failed to parse package
if (package) wiki_package_free(package);
}
}
list_iterator_destroy(li_iterator);
list_destroy(lis);
free(category);
}
list_iterator_destroy(heading_iterator);
list_destroy(h2s);
}

gumbo_destroy_output(&kGumboDefaultOptions, output);
return pkgs;
}

/**
* Get a list of packages from the given GitHub wiki `url`.
*/
list_t *github_registry_fetch(const char *url) {
http_get_response_t *res = http_get(url);
if (!res->ok) return NULL;

list_t *list = wiki_registry_parse(res->data);
http_get_free(res);
return list;
}

8 changes: 8 additions & 0 deletions deps/wiki-registry/github-registry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef CLIB_GITHUB_REGISTRY_H
#define CLIB_GITHUB_REGISTRY_H

#include "list/list.h"

list_t* github_registry_fetch(const char *url);

#endif //CLIB_GITHUB_REGISTRY_H
12 changes: 12 additions & 0 deletions deps/wiki-registry/gitlab-registry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// gitlab-registry.c
//
// Copyright (c) 2020 Elbert van de Put
// MIT licensed
//
#include "gitlab-registry.h"

list_t* gitlab_registry_fetch(const char *url) {
return NULL;
}

8 changes: 8 additions & 0 deletions deps/wiki-registry/gitlab-registry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef CLIB_GITLAB_REGISTRY_H
#define CLIB_GITLAB_REGISTRY_H

#include "list/list.h"

list_t* gitlab_registry_fetch(const char *url);

#endif //CLIB_GITLAB_REGISTRY_H
17 changes: 17 additions & 0 deletions deps/wiki-registry/wiki-registry-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef WIKI_REGISTRY_HELPER_H
#define WIKI_REGISTRY_HELPER_H
// DO NOT INCLUDE. THIS HEADER IS INTERNAL ONLY
#include "wiki-registry.h"

struct wiki_package_t {
char *repo;
char *href;
char *description;
char *category;
};

wiki_package_ptr_t wiki_package_new();

void wiki_package_free(wiki_package_ptr_t pkg);

#endif //WIKI_REGISTRY_HELPER_H
Loading