Skip to content

Commit 9b54ae0

Browse files
committed
registry: Start with a gitlab registry.
1 parent b18b78a commit 9b54ae0

File tree

12 files changed

+162
-47
lines changed

12 files changed

+162
-47
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ RM = rm -f
1212
MKDIR = mkdir -p
1313

1414
SRC = $(wildcard src/*.c)
15-
COMMON_SRC = $(wildcard src/common/*.c)
16-
ALL_SRC = $(wildcard src/*.c src/*.h src/common/*.c src/common/*.h test/package/*.c test/cache/*.c)
15+
COMMON_SRC = $(wildcard src/common/*.c src/registry/*.c)
16+
ALL_SRC = $(wildcard src/*.c src/*.h src/common/*.c src/common/*.h src/registry/*.c src/registry/*.h test/package/*.c test/cache/*.c)
1717
SDEPS = $(wildcard deps/*/*.c)
1818
ODEPS = $(SDEPS:.c=.o)
1919
DEPS = $(filter-out $(ODEPS), $(SDEPS))
@@ -26,7 +26,7 @@ ifdef STATIC
2626
CFLAGS += -DCURL_STATICLIB -std=c99 -Ideps -Wall -Werror=return-type -Wno-unused-function -U__STRICT_ANSI__ $(shell deps/curl/bin/curl-config --cflags)
2727
LDFLAGS += -static $(shell deps/curl/bin/curl-config --static-libs)
2828
else
29-
CFLAGS += -std=c99 -Ideps -Wall -Wno-unused-function -U__STRICT_ANSI__ $(shell curl-config --cflags)
29+
CFLAGS += -std=c99 -Ideps -g -Wall -Werror=return-type -Wno-unused-function -U__STRICT_ANSI__ $(shell curl-config --cflags)
3030
LDFLAGS += $(shell curl-config --libs)
3131
endif
3232

clib.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,16 @@
3737
"stephenmathieson/debug.c": "0.0.0",
3838
"stephenmathieson/tempdir.c": "0.0.2",
3939
"isty001/copy": "0.0.0",
40-
"stephenmathieson/rimraf.c": "0.1.0"
40+
"stephenmathieson/rimraf.c": "0.1.0",
41+
"thlorenz/gumbo-parser.c": "*",
42+
"stephenmathieson/http-get.c": "*",
43+
"stephenmathieson/gumbo-text-content.c": "*",
44+
"stephenmathieson/gumbo-get-element-by-id.c": "*",
45+
"stephenmathieson/gumbo-get-elements-by-tag-name.c": "*",
46+
"clibs/list": "*",
47+
"jwerle/url.h": "0.0.*"
4148
},
4249
"development": {
4350
"stephenmathieson/describe.h": "2.0.1"
4451
}
45-
}
52+
}

deps/wiki-registry/gitlab-registry.c

Lines changed: 0 additions & 12 deletions
This file was deleted.

deps/wiki-registry/package.json

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/clib-search.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "strdup/strdup.h"
2020
#include "tempdir/tempdir.h"
2121
#include "version.h"
22-
#include "wiki-registry/wiki-registry.h"
22+
#include "registry/wiki-registry.h"
2323
#include <stdio.h>
2424
#include <stdlib.h>
2525
#include <string.h>
File renamed without changes.
File renamed without changes.

src/registry/gitlab-registry.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//
2+
// gitlab-registry.c
3+
//
4+
// Copyright (c) 2020 Elbert van de Put
5+
// MIT licensed
6+
//
7+
#include "gitlab-registry.h"
8+
#include <string.h>
9+
#include "gumbo-text-content/gumbo-text-content.h"
10+
#include "gumbo-get-element-by-id/get-element-by-id.h"
11+
#include "gumbo-get-elements-by-tag-name/get-elements-by-tag-name.h"
12+
#include "http-get/http-get.h"
13+
#include <curl/curl.h>
14+
#include "substr/substr.h"
15+
#include "strdup/strdup.h"
16+
#include "case/case.h"
17+
#include "trim/trim.h"
18+
#include "wiki-registry-internal.h"
19+
20+
/**
21+
* Add `href` to the given `package`.
22+
* We assume that all packages listed by a registry live on the same platform as the registry.
23+
*/
24+
static void add_package_href(wiki_package_ptr_t self, const char* hostname) {
25+
size_t len = strlen(self->repo) + strlen(hostname);
26+
self->href = malloc(len);
27+
if (self->href)
28+
sprintf(self->href, "https://%s/%s", hostname, self->repo);
29+
}
30+
31+
/**
32+
* Parse the given wiki `li` into a package.
33+
*/
34+
static wiki_package_ptr_t parse_li(GumboNode *li, const char* hostname) {
35+
wiki_package_ptr_t self = wiki_package_new();
36+
char *text = NULL;
37+
38+
if (!self) goto cleanup;
39+
40+
text = gumbo_text_content(li);
41+
if (!text) goto cleanup;
42+
43+
// TODO support unicode dashes
44+
char *tok = strstr(text, " - ");
45+
if (!tok) goto cleanup;
46+
47+
int pos = tok - text;
48+
self->repo = substr(text, 0, pos);
49+
self->description = substr(text, pos + 3, -1);
50+
if (!self->repo || !self->description) goto cleanup;
51+
trim(self->description);
52+
trim(self->repo);
53+
54+
add_package_href(self, hostname);
55+
56+
cleanup:
57+
free(text);
58+
return self;
59+
}
60+
61+
/**
62+
* Parse a list of packages from the given `html`
63+
*/
64+
static list_t *wiki_registry_parse(const char* hostname, const char *html) {
65+
GumboOutput *output = gumbo_parse(html);
66+
list_t *pkgs = list_new();
67+
68+
GumboNode *body = gumbo_get_element_by_id("wiki-body", output->root);
69+
if (body) {
70+
// grab all category `<h2 />`s
71+
list_t *h2s = gumbo_get_elements_by_tag_name("h2", body);
72+
list_node_t *heading_node;
73+
list_iterator_t *heading_iterator = list_iterator_new(h2s, LIST_HEAD);
74+
while ((heading_node = list_iterator_next(heading_iterator))) {
75+
GumboNode *heading = (GumboNode *) heading_node->val;
76+
char *category = gumbo_text_content(heading);
77+
// die if we failed to parse a category, as it's
78+
// almost certinaly a malloc error
79+
if (!category) break;
80+
trim(case_lower(category));
81+
GumboVector *siblings = &heading->parent->v.element.children;
82+
size_t pos = heading->index_within_parent;
83+
84+
// skip elements until the UL
85+
// TODO: don't hardcode position here
86+
// 2:
87+
// 1 - whitespace
88+
// 2 - actual node
89+
GumboNode *ul = siblings->data[pos + 2];
90+
if (GUMBO_TAG_UL != ul->v.element.tag) {
91+
free(category);
92+
continue;
93+
}
94+
95+
list_t *lis = gumbo_get_elements_by_tag_name("li", ul);
96+
list_iterator_t *li_iterator = list_iterator_new(lis, LIST_HEAD);
97+
list_node_t *li_node;
98+
while ((li_node = list_iterator_next(li_iterator))) {
99+
wiki_package_ptr_t package = parse_li(li_node->val, hostname);
100+
if (package && package->description) {
101+
package->category = strdup(category);
102+
list_rpush(pkgs, list_node_new(package));
103+
} else {
104+
// failed to parse package
105+
if (package) wiki_package_free(package);
106+
}
107+
}
108+
list_iterator_destroy(li_iterator);
109+
list_destroy(lis);
110+
free(category);
111+
}
112+
list_iterator_destroy(heading_iterator);
113+
list_destroy(h2s);
114+
}
115+
116+
gumbo_destroy_output(&kGumboDefaultOptions, output);
117+
return pkgs;
118+
}
119+
120+
/**
121+
* Get a list of packages from the given gitlab wiki `url`.
122+
*/
123+
list_t *gitlab_registry_fetch(const char *url, const char* hostname) {
124+
http_get_response_t *res = http_get(url);
125+
if (!res->ok) return NULL;
126+
127+
list_t *list = wiki_registry_parse(url, res->data);
128+
http_get_free(res);
129+
return list;
130+
}
131+

deps/wiki-registry/gitlab-registry.h renamed to src/registry/gitlab-registry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44
#include "list/list.h"
55

6-
list_t* gitlab_registry_fetch(const char *url);
6+
list_t* gitlab_registry_fetch(const char* url, const char* hostname);
77

88
#endif //CLIB_GITLAB_REGISTRY_H

0 commit comments

Comments
 (0)