commit - ee61b6d3d5750355ac28ca4afae5c04deb1a1fa2
commit + 82ebf666930f3ea5b44663d1fede65ed22282361
blob - b666240f68350f4108c0af0dcc49d57b93cc1c42
blob + 33820f922ef8ee50b6236805c495361c960616a7
--- include/got_fetch.h
+++ include/got_fetch.h
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* IANA assigned */
+#define GOT_DEFAULT_GIT_PORT 9418
+#define GOT_DEFAULT_GIT_PORT_STR "9418"
+
+const struct got_error *got_fetch_parse_uri(char **, char **, char **,
+ char **, char **, const char *);
const struct got_error* got_fetch(char *, char *, char *);
blob - 052353d32d46bd93e82ad56c5da026ac56999ec5
blob + b4ee27f466629f5422a50913c157a5910cd95fd3
--- lib/fetch.c
+++ lib/fetch.c
#include "got_worktree.h"
#include "got_object.h"
#include "got_opentemp.h"
+#include "got_fetch.h"
#include "got_lib_delta.h"
#include "got_lib_inflate.h"
return 0;
}
-static int
-grab(char *dst, int n, char *p, char *e)
-{
- int l;
-
- l = e - p;
- if (l >= n) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return strlcpy(dst, p, l + 1);
-}
-
static const struct got_error *
dial_ssh(int *fetchfd, char *host, char *port, char *path, char *direction)
{
return err;
}
-int
-got_parse_uri(char *uri, char *proto, char *host, char *port, char *path, char *repo)
+const struct got_error *
+got_fetch_parse_uri(char **proto, char **host, char **port,
+ char **server_path, char **repo_name, const char *uri)
{
+ const struct got_error *err = NULL;
char *s, *p, *q;
int n, hasport;
+ *proto = *host = *port = *server_path = *repo_name = NULL;
+
p = strstr(uri, "://");
if (!p) {
- //werrstr("missing protocol");
- return -1;
+ return got_error(GOT_ERR_PARSE_URI);
}
- if (grab(proto, GOT_PROTOMAX, uri, p) == -1)
- return -1;
- hasport = (strcmp(proto, "git") == 0 || strstr(proto, "http") == proto);
+ *proto = strndup(uri, p - uri);
+ if (proto == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+
+ hasport = (strcmp(*proto, "git") == 0 ||
+ strstr(*proto, "http") == *proto);
s = p + 3;
p = NULL;
if (!hasport) {
if (p == NULL)
p = strstr(s, "/");
if (p == NULL || strlen(p) == 1) {
- //werrstr("missing path");
- return -1;
+ err = got_error(GOT_ERR_PARSE_URI);
+ goto done;
}
q = memchr(s, ':', p - s);
if (q) {
- grab(host, GOT_HOSTMAX, s, q);
- grab(port, GOT_PORTMAX, q + 1, p);
- }else{
- grab(host, GOT_HOSTMAX, s, p);
- snprintf(port, GOT_PORTMAX, "9418");
+ *host = strndup(s, q - s);
+ if (*host == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ *port = strndup(q + 1, p - (q + 1));
+ if (*port == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ } else {
+ *host = strndup(s, p - s);
+ if (*host == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (asprintf(port, "%u", GOT_DEFAULT_GIT_PORT) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
}
- snprintf(path, GOT_PATHMAX, "%s", p);
+ *server_path = strdup(p);
+ if (*server_path == NULL) {
+ err = got_error_from_errno("strdup");
+ goto done;
+ }
+
p = strrchr(p, '/') + 1;
if (!p || strlen(p) == 0) {
//werrstr("missing repository in uri");
- return -1;
+ err = got_error(GOT_ERR_PARSE_URI);
+ goto done;
}
n = strlen(p);
if (hassuffix(p, ".git"))
n -= 4;
- grab(repo, GOT_REPOMAX, p, p + n);
- return 0;
+ *repo_name = strndup(p, (p + n) - p);
+ if (*repo_name == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+done:
+ if (err) {
+ free(*proto);
+ *proto = NULL;
+ free(*host);
+ *host = NULL;
+ free(*port);
+ *port = NULL;
+ free(*server_path);
+ *server_path = NULL;
+ free(*repo_name);
+ *repo_name = NULL;
+ }
+ return err;
}
const struct got_error*
got_fetch(char *uri, char *branch_filter, char *destdir)
{
- char proto[GOT_PROTOMAX], host[GOT_HOSTMAX], port[GOT_PORTMAX];
- char repo_name[GOT_REPOMAX], server_path[GOT_PATHMAX];
+ char *proto, *host, *port, *repo_name, *server_path;
int imsg_fetchfds[2], imsg_idxfds[2], fetchfd = -1;
int packfd = -1, npackfd = -1, idxfd = -1, nidxfd = -1;
int status, done = 0;
TAILQ_INIT(&symrefs);
fetchfd = -1;
- if (got_parse_uri(uri, proto, host, port, server_path, repo_name) == -1)
- return got_error(GOT_ERR_PARSE_URI);
+ err = got_fetch_parse_uri(&proto, &host, &port, &server_path,
+ &repo_name, uri);
+ if (err)
+ return err;
if (destdir == NULL) {
if (asprintf(&default_destdir, "%s.git", repo_name) == -1)
return got_error_from_errno("asprintf");
blob - 060d69c317d74037521f5d1b4a7653dc63a4fb41
blob + 5c2026319bf17285a069070e877b8280c58877a5
--- regress/Makefile
+++ regress/Makefile
-SUBDIR = cmdline delta idset path
+SUBDIR = cmdline delta idset path fetch
.include <bsd.subdir.mk>
blob - /dev/null
blob + 94a84612acbddadb06374e6a4344fe42b4b414f2 (mode 644)
--- /dev/null
+++ regress/fetch/Makefile
+.PATH:${.CURDIR}/../../lib
+
+PROG = fetch_test
+SRCS = error.c privsep.c reference.c sha1.c object.c object_parse.c path.c \
+ opentemp.c repository.c lockfile.c object_cache.c pack.c inflate.c \
+ deflate.c delta.c delta_cache.c object_idset.c object_create.c \
+ fetch.c fetch_test.c
+
+CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
+LDADD = -lutil -lz
+
+NOMAN = yes
+
+.include <bsd.regress.mk>
blob - /dev/null
blob + 3235b8bc1059ed5309407ac94a0054ab55e72bb8 (mode 644)
--- /dev/null
+++ regress/fetch/fetch_test.c
+/*
+ * Copyright (c) 2020 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/queue.h>
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <sha1.h>
+#include <zlib.h>
+#include <time.h>
+
+#include "got_error.h"
+#include "got_object.h"
+#include "got_fetch.h"
+
+#include "got_lib_object_idset.h"
+#include "got_lib_sha1.h"
+#include "got_lib_inflate.h"
+#include "got_lib_delta.h"
+
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+static int verbose;
+
+void
+test_printf(char *fmt, ...)
+{
+ va_list ap;
+
+ if (!verbose)
+ return;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+static int
+fetch_parse_uri(void)
+{
+ const struct got_error *err = NULL;
+ struct parse_uri_test {
+ const char *uri;
+ const char *proto;
+ const char *host;
+ const char *port;
+ const char *server_path;
+ const char *repo_name;
+ int errcode;
+ } test_data[] = {
+ { "", NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+ { "git:", NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+ { "git://localhost/",
+ NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+ { "git://localhost////",
+ NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+ { "git://127.0.0.1/git/",
+ NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+ { "git:///127.0.0.1/git/",
+ NULL, NULL, NULL, NULL, NULL, GOT_ERR_PARSE_URI },
+
+ { "git://127.0.0.1/git/myrepo",
+ "git", "localhost", GOT_DEFAULT_GIT_PORT_STR, "git",
+ "myrepo", GOT_ERR_OK },
+ { "http://127.0.0.1/git/myrepo",
+ "http", "localhost", GOT_DEFAULT_GIT_PORT_STR, "git",
+ "myrepo", GOT_ERR_OK },
+ { "gopher://127.0.0.1/git/myrepo",
+ "gopher", "localhost", GOT_DEFAULT_GIT_PORT_STR, "git",
+ "myrepo", GOT_ERR_OK },
+
+ { "git://127.0.0.1:22/git/myrepo",
+ "git", "localhost", "22", "git", "myrepo", GOT_ERR_OK },
+
+ { "git://127.0.0.1/git/repos/foo/bar/myrepo.git",
+ "git", "localhost", GOT_DEFAULT_GIT_PORT_STR,
+ "git/repos/foo/bar", "myrepo", GOT_ERR_OK },
+ { "https://127.0.0.1/git/repos/foo/../bar/myrepo.git",
+ "https", "localhost", GOT_DEFAULT_GIT_PORT_STR,
+ "git/repos/foo/../bar", "myrepo", GOT_ERR_OK },
+
+ };
+ int i;
+
+ for (i = 0; i < nitems(test_data); i++) {
+ const char *uri = test_data[i].uri;
+ const char *expected_proto = test_data[i].proto;
+ const char *expected_host = test_data[i].host;
+ const char *expected_port = test_data[i].port;
+ const char *expected_server_path = test_data[i].server_path;
+ const char *expected_repo_name = test_data[i].repo_name;
+ char *proto, *host, *port, *server_path, *repo_name;
+
+ err = got_fetch_parse_uri(&proto, &host, &port, &server_path,
+ &repo_name, uri);
+ if (err && err->code != test_data[i].errcode) {
+ test_printf("%d: error code %d; expected %d\n",
+ i, err->code, test_data[i].errcode);
+ return 0;
+ }
+
+ if (expected_proto == NULL && proto != NULL) {
+ test_printf("%d: proto %s; expected NULL\n", i, proto);
+ return 0;
+ }
+ if (expected_host == NULL && host != NULL) {
+ test_printf("%d: host %s; expected NULL\n", i, host);
+ return 0;
+ }
+ if (expected_port == NULL && port != NULL) {
+ test_printf("%d: port %s; expected NULL\n", i, port);
+ return 0;
+ }
+ if (expected_server_path == NULL && server_path != NULL) {
+ test_printf("%d: server path %s; expected NULL\n", i,
+ server_path);
+ return 0;
+ }
+ if (expected_repo_name == NULL && repo_name != NULL) {
+ test_printf("%d: repo name %s; expected NULL\n", i,
+ repo_name);
+ return 0;
+ }
+
+ if (expected_proto != NULL && proto == NULL) {
+ test_printf("%d: proto NULL; expected %s\n", i,
+ expected_proto);
+ return 0;
+ }
+ if (expected_host != NULL && host == NULL) {
+ test_printf("%d: host NULL; expected %s\n", i,
+ expected_host);
+ return 0;
+ }
+ if (expected_port != NULL && port == NULL) {
+ test_printf("%d: port NULL; expected %s\n", i,
+ expected_port);
+ return 0;
+ }
+ if (expected_server_path != NULL && server_path == NULL) {
+ test_printf("%d: server path %s; expected %s\n", i,
+ expected_server_path);
+ return 0;
+ }
+ if (expected_repo_name != NULL && repo_name == NULL) {
+ test_printf("%d: repo name NULL; expected %s\n", i,
+ repo_name);
+ return 0;
+ }
+
+ if (expected_proto != NULL && strcmp(expected_proto, proto)) {
+ test_printf("%d: proto %s; expected %s\n", i, proto,
+ expected_proto);
+ return 0;
+ }
+
+ free(proto);
+ proto = NULL;
+ free(host);
+ host = NULL;
+ free(port);
+ port = NULL;
+ free(server_path);
+ server_path = NULL;
+ free(repo_name);
+ repo_name = NULL;
+ }
+
+ return 1;
+}
+
+#define RUN_TEST(expr, name) \
+ { test_ok = (expr); \
+ printf("test_%s %s\n", (name), test_ok ? "ok" : "failed"); \
+ failure = (failure || !test_ok); }
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: fetch_test [-v]\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int test_ok = 0, failure = 0;
+ int ch;
+
+#ifndef PROFILE
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+#endif
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ return 1;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ RUN_TEST(fetch_parse_uri(), "fetch_parse_uri");
+
+ return failure ? 1 : 0;
+}