commit 7d4057662589d6190d63231f5ea868a05f2780d2 from: Stefan Sperling date: Tue Jul 30 13:01:59 2019 UTC retire C tests which depended on Got's own Git repository to run commit - 53ccebc212c162c70f666f060b461d9dccdca647 commit + 7d4057662589d6190d63231f5ea868a05f2780d2 blob - a7df9bcfd7dd5240b4bf896836d2bc6db0cb92ac blob + 45158e76977b2c703c3ea2388bd8cc163bd7ce31 --- README +++ README @@ -60,9 +60,9 @@ about how the problem can be reproduced. A regression written in any case to verify a fix and prevent the problem from resurfacing. It is also possible to write test cases in C. Various examples of this -exist in the regress/ directory. Most such tests are unit tests written -before Got's command line interface was available; it is unlikely that a -problem found during regular usage will require a test to be written in C. +exist in the regress/ directory. Most such tests are unit tests; it is +unlikely that a problem found during regular usage will require a test +to be written in C. Some areas of code, such as the tog UI, are not covered by automated tests. Please always try to find a way to trigger your problem via the command line blob - ead26b8028b6eabf832d64f2b8d487d55f790b32 blob + 7553c630ced30b2ae8f77cad74ae23f3f298c388 --- got-dist.txt +++ got-dist.txt @@ -98,18 +98,12 @@ /libexec/got-read-tag/Makefile /libexec/got-read-tag/got-read-tag.c /regress -/regress/repository -/regress/repository/Makefile -/regress/repository/repository_test.c /regress/idset /regress/idset/Makefile /regress/idset/idset_test.c /regress/delta /regress/delta/Makefile /regress/delta/delta_test.c -/regress/worktree -/regress/worktree/Makefile -/regress/worktree/worktree_test.c /regress/Makefile /regress/Makefile.inc /regress/cmdline blob - b5554554510d2ea5d8e632dd20c19931b5da7aa1 blob + 060d69c317d74037521f5d1b4a7653dc63a4fb41 --- regress/Makefile +++ regress/Makefile @@ -1,3 +1,3 @@ -SUBDIR = cmdline delta idset path repository worktree +SUBDIR = cmdline delta idset path .include blob - 6341b049647beede14d907a8e07ff6b709036d9d (mode 644) blob + /dev/null --- regress/repository/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PATH:${.CURDIR}/../../lib - -PROG = repository_test -SRCS = path.c repository.c error.c reference.c object.c object_cache.c \ - object_idset.c object_parse.c opentemp.c sha1.c diff.c diffreg.c \ - pack.c privsep.c delta.c fileindex.c worktree.c inflate.c \ - buf.c worklist.c rcsutil.c diff3.c lockfile.c deflate.c \ - object_create.c repository_test.c - -CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib -LDADD = -lutil -lz - -NOMAN = yes - -.include blob - c195445da886beac77bfd5c142d4a744bc55f866 (mode 644) blob + /dev/null --- regress/repository/repository_test.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (c) 2017 Stefan Sperling - * - * 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "got_error.h" -#include "got_object.h" -#include "got_reference.h" -#include "got_repository.h" -#include "got_diff.h" -#include "got_opentemp.h" -#include "got_privsep.h" -#include "got_path.h" - - -#ifndef nitems -#define nitems(_a) (sizeof(_a) / sizeof((_a)[0])) -#endif - -#define GOT_REPO_PATH "../../../" - -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 const struct got_error * -print_commit_object(struct got_object_id *, struct got_repository *); - -static const struct got_error * -print_parent_commits(struct got_commit_object *commit, - struct got_repository *repo) -{ - const struct got_object_id_queue *parent_ids; - struct got_object_qid *qid; - const struct got_error *err = NULL; - - parent_ids = got_object_commit_get_parent_ids(commit); - SIMPLEQ_FOREACH(qid, parent_ids, entry) { - err = print_commit_object(qid->id, repo); - if (err) - break; - } - - return err; -} - -static const struct got_error * -print_tree_object(struct got_object_id *id, char *parent, - struct got_repository *repo) -{ - struct got_tree_object *tree; - const struct got_tree_entries *entries; - struct got_tree_entry *te; - const struct got_error *err; - - err = got_object_open_as_tree(&tree, repo, id); - if (err != NULL) - return err; - - entries = got_object_tree_get_entries(tree); - SIMPLEQ_FOREACH(te, &entries->head, entry) { - char *next_parent; - char *hex; - - err = got_object_id_str(&hex, te->id); - if (err) - break; - - if (!S_ISDIR(te->mode)) { - test_printf("%s %s/%s\n", hex, parent, te->name); - free(hex); - continue; - } - test_printf("%s %s/%s\n", hex, parent, te->name); - free(hex); - - if (asprintf(&next_parent, "%s/%s", parent, te->name) == -1) { - err = got_error_from_errno("asprintf"); - break; - } - - err = print_tree_object(te->id, next_parent, repo); - free(next_parent); - if (err) - break; - } - - got_object_tree_close(tree); - return err; -} - -static const struct got_error * -print_commit_object(struct got_object_id *id, struct got_repository *repo) -{ - struct got_commit_object *commit; - const struct got_object_id_queue *parent_ids; - struct got_object_qid *qid; - char *buf; - const struct got_error *err; - int obj_type; - - err = got_object_open_as_commit(&commit, repo, id); - if (err) - return err; - - err = got_object_id_str(&buf, id); - if (err) { - got_object_commit_close(commit); - return err; - } - test_printf("tree: %s\n", buf); - free(buf); - test_printf("parent%s: ", - (got_object_commit_get_nparents(commit) == 1) ? "" : "s"); - parent_ids = got_object_commit_get_parent_ids(commit); - SIMPLEQ_FOREACH(qid, parent_ids, entry) { - err = got_object_id_str(&buf, qid->id); - if (err) { - got_object_commit_close(commit); - return err; - } - test_printf("%s\n", buf); - free(buf); - } - test_printf("author: %s\n", got_object_commit_get_author(commit)); - test_printf("committer: %s\n", got_object_commit_get_committer(commit)); - test_printf("log: %s\n", got_object_commit_get_logmsg(commit)); - - err = got_object_get_type(&obj_type, repo, - got_object_commit_get_tree_id(commit)); - if (err != NULL) { - got_object_commit_close(commit); - return err; - } - if (obj_type == GOT_OBJ_TYPE_TREE) - test_printf("\n"); - - err = print_parent_commits(commit, repo); - got_object_commit_close(commit); - - return err; -} - -static int -repo_read_log(const char *repo_path) -{ - const struct got_error *err; - struct got_repository *repo; - struct got_reference *head_ref; - struct got_object_id *id; - char *buf; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - return 0; - err = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0); - if (err != NULL || head_ref == NULL) - return 0; - err = got_ref_resolve(&id, repo, head_ref); - if (err != NULL || head_ref == NULL) - return 0; - err = got_object_id_str(&buf, id); - if (err != NULL) - return 0; - test_printf("HEAD is at %s\n", buf); - free(buf); - err = print_commit_object(id, repo); - if (err) - return 0; - free(id); - got_ref_close(head_ref); - got_repo_close(repo); - return 1; -} - -static int -repo_read_tree(const char *repo_path) -{ - const char *tree_sha1 = "6cc96e0e093fb30630ba7f199d0a008b24c6a690"; - const struct got_error *err; - struct got_repository *repo; - struct got_object_id *id; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - return 0; - err = got_object_resolve_id_str(&id, repo, tree_sha1); - if (err != NULL) - return 0; - - print_tree_object(id, "", repo); - test_printf("\n"); - - got_repo_close(repo); - return (err == NULL); -} - -static int -repo_read_blob(const char *repo_path) -{ - const char *blob_sha1 = "141f5fdc96126c1f4195558560a3c915e3d9b4c3"; - const struct got_error *err; - struct got_repository *repo; - struct got_object_id *id; - struct got_blob_object *blob; - int i; - size_t len; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - return 0; - err = got_object_resolve_id_str(&id, repo, blob_sha1); - if (err != NULL) - return 0; - err = got_object_open_as_blob(&blob, repo, id, 64); - if (err != NULL) - return 0; - - test_printf("\n"); - do { - const uint8_t *buf = got_object_blob_get_read_buf(blob); - err = got_object_blob_read_block(&len, blob); - if (err) - break; - for (i = 0; i < len; i++) - test_printf("%c", buf[i]); - } while (len != 0); - test_printf("\n"); - - got_object_blob_close(blob); - got_repo_close(repo); - return (err == NULL); -} - -static int -repo_diff_blob(const char *repo_path) -{ - const char *blob1_sha1 = "141f5fdc96126c1f4195558560a3c915e3d9b4c3"; - const char *blob2_sha1 = "de7eb21b21c7823a753261aadf7cba35c9580fbf"; - const struct got_error *err; - struct got_repository *repo; - struct got_object_id *id1, *id2; - struct got_blob_object *blob1; - struct got_blob_object *blob2; - FILE *outfile; - int i; - char *line; - size_t len; - const char delim[3] = {'\0', '\0', '\0'}; - const char *expected_output[] = { - "blob - 141f5fdc96126c1f4195558560a3c915e3d9b4c3", - "blob + de7eb21b21c7823a753261aadf7cba35c9580fbf", - "--- 141f5fdc96126c1f4195558560a3c915e3d9b4c3", - "+++ de7eb21b21c7823a753261aadf7cba35c9580fbf", - "@@ -1,10 +1,10 @@", - " .PATH:${.CURDIR}/../../lib", - " ", - " PROG = repository_test", - "-SRCS = path.c repository.c error.c refs.c repository_test.c", - "+SRCS = path.c repository.c error.c refs.c object.c sha1.c repository_test.c", - " ", - " CPPFLAGS = -I${.CURDIR}/../../include", - "-LDADD = -lutil", - "+LDADD = -lutil -lz", - " ", - " NOMAN = yes" - }; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - return 0; - - err = got_object_resolve_id_str(&id1, repo, blob1_sha1); - if (err != NULL) - return 0; - - err = got_object_resolve_id_str(&id2, repo, blob2_sha1); - if (err != NULL) - return 0; - - err = got_object_open_as_blob(&blob1, repo, id1, 512); - if (err != NULL) - return 0; - - err = got_object_open_as_blob(&blob2, repo, id2, 512); - if (err != NULL) - return 0; - - test_printf("\n"); - outfile = got_opentemp(); - if (outfile == NULL) - return 0; - got_diff_blob(blob1, blob2, NULL, NULL, 3, outfile); - rewind(outfile); - i = 0; - while ((line = fparseln(outfile, &len, NULL, delim, 0)) != NULL) { - test_printf(line); - test_printf("\n"); - if (i < nitems(expected_output) && - strcmp(line, expected_output[i]) != 0) { - test_printf("diff output mismatch; expected: '%s'\n", - expected_output[i]); - return 0; - } - i++; - } - if (fclose(outfile) != 0 && err == NULL) - err = got_error_from_errno("fclose"); - test_printf("\n"); - if (i != nitems(expected_output) + 1) { - test_printf("number of lines expected: %d; actual: %d\n", - nitems(expected_output), i - 1); - return 0; - } - - got_object_blob_close(blob1); - got_object_blob_close(blob2); - got_repo_close(repo); - return (err == NULL); -} - -static int -repo_diff_tree(const char *repo_path) -{ - const char *tree1_sha1 = "1efc41caf761a0a1f119d0c5121eedcb2e7a88c3"; - const char *tree2_sha1 = "4aa8f2933839ff8a8fb3f905a4c232d22c6ff5f3"; - const struct got_error *err; - struct got_repository *repo; - struct got_object_id *id1; - struct got_object_id *id2; - struct got_tree_object *tree1; - struct got_tree_object *tree2; - FILE *outfile; - struct got_diff_blob_output_unidiff_arg arg; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - return 0; - - err = got_object_resolve_id_str(&id1, repo, tree1_sha1); - if (err != NULL) - return 0; - err = got_object_resolve_id_str(&id2, repo, tree2_sha1); - if (err != NULL) - return 0; - - err = got_object_open_as_tree(&tree1, repo, id1); - if (err != NULL) - return 0; - - err = got_object_open_as_tree(&tree2, repo, id2); - if (err != NULL) - return 0; - - if (!verbose) { - outfile = fopen("/dev/null", "w+"); - if (outfile == NULL) - return 0; - } else - outfile = stdout; - test_printf("\n"); - arg.diff_context = 3; - arg.outfile = outfile; - got_diff_tree(tree1, tree2, "", "", repo, - got_diff_blob_output_unidiff, &arg, 1); - test_printf("\n"); - - got_object_tree_close(tree1); - got_object_tree_close(tree2); - got_repo_close(repo); - return (err == NULL); -} - -#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: repository_test [-v] [REPO_PATH]\n"); -} - -static const struct got_error * -apply_unveil(const char *repo_path) -{ - const struct got_error *error; - - if (repo_path) { - if (unveil(repo_path, "r") != 0) - return got_error_from_errno2("unveil", repo_path); - } - - if (unveil("/tmp", "rwc") != 0) - return got_error_from_errno2("unveil", "/tmp"); - - if (unveil("/dev/null", "rwc") != 0) - return got_error_from_errno2("unveil", "/dev/null"); - - error = got_privsep_unveil_exec_helpers(); - if (error != NULL) - return error; - - if (unveil(NULL, NULL) != 0) - return got_error_from_errno("unveil"); - - return NULL; -} - -int -main(int argc, char *argv[]) -{ - int test_ok = 0, failure = 0; - char *repo_path; - int ch; - const struct got_error *error; - -#ifndef PROFILE - if (pledge("stdio rpath wpath cpath proc exec sendfd unveil", 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; - - switch (argc) { - case 0: - repo_path = realpath(GOT_REPO_PATH, NULL); - break; - case 1: - repo_path = realpath(argv[0], NULL); - break; - default: - usage(); - return 1; - } - if (repo_path == NULL) { - fprintf(stderr, "realpath: %s\n", strerror(errno)); - return 1; - } - - error = apply_unveil(repo_path); - if (error) { - fprintf(stderr, "unveil: %s\n", error->msg); - free(repo_path); - return 1; - } - - RUN_TEST(repo_read_tree(repo_path), "read_tree"); - RUN_TEST(repo_read_log(repo_path), "read_log"); - RUN_TEST(repo_read_blob(repo_path), "read_blob"); - RUN_TEST(repo_diff_blob(repo_path), "diff_blob"); - RUN_TEST(repo_diff_tree(repo_path), "diff_tree"); - - free(repo_path); - return failure ? 1 : 0; -} blob - c29a98dabd56d5ccc65fa9042aa0141e6ef953dc (mode 644) blob + /dev/null --- regress/worktree/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PATH:${.CURDIR}/../../lib - -PROG = worktree_test -SRCS = worktree.c repository.c object.c object_cache.c object_idset.c \ - object_parse.c opentemp.c path.c error.c reference.c sha1.c pack.c \ - privsep.c delta.c inflate.c fileindex.c \ - buf.c worklist.c rcsutil.c diff.c diffreg.c diff3.c lockfile.c \ - deflate.c object_create.c worktree_test.c - -CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib -LDADD = -lutil -lz - -NOMAN = yes - -.include blob - 3df09c5d054b2011eb32474bd2a2f373638965ed (mode 644) blob + /dev/null --- regress/worktree/worktree_test.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2018, 2019 Stefan Sperling - * - * 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "got_error.h" -#include "got_object.h" -#include "got_reference.h" -#include "got_repository.h" -#include "got_path.h" -#include "got_worktree.h" -#include "got_opentemp.h" -#include "got_privsep.h" - -#include "got_lib_worktree.h" - -#define GOT_REPO_PATH "../../../" - -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 -remove_got_dir(const char *worktree_path) -{ - char *path; - - if (asprintf(&path, "%s/%s", worktree_path, GOT_WORKTREE_GOT_DIR) == -1) - return 0; - rmdir(path); - free(path); - return 1; -} - -static int -remove_meta_file(const char *worktree_path, const char *name) -{ - char *path; - - if (asprintf(&path, "%s/%s/%s", worktree_path, GOT_WORKTREE_GOT_DIR, - name) == -1) - return 0; - unlink(path); - free(path); - return 1; -} - -static const struct got_error * -remove_worktree_base_ref(struct got_worktree *worktree, - struct got_repository *repo) -{ - const struct got_error *err = NULL; - struct got_reference *base_ref = NULL; - char *refname = NULL; - - err = got_worktree_get_base_ref_name(&refname, worktree); - if (err) - return err; - - err = got_ref_open(&base_ref, repo, refname, 0); - if (err) - goto done; - - err = got_ref_delete(base_ref, repo); -done: - if (base_ref) - got_ref_close(base_ref); - free(refname); - return err; - -} - -static int -remove_worktree(const char *worktree_path) -{ - if (!remove_meta_file(worktree_path, GOT_WORKTREE_HEAD_REF)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_BASE_COMMIT)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_FILE_INDEX)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_REPOSITORY)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_PATH_PREFIX)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_LOCK)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_FORMAT)) - return 0; - if (!remove_meta_file(worktree_path, GOT_WORKTREE_UUID)) - return 0; - if (!remove_got_dir(worktree_path)) - return 0; - if (rmdir(worktree_path) == -1) - return 0; - return 1; -} - -static int -read_meta_file(char **content, const char *path) -{ - FILE *f; - size_t len; - const char delim[3] = {'\0', '\0', '\0'}; - int ret = 0; - - f = fopen(path, "r"); - if (f == NULL) - return errno; - - *content = fparseln(f, &len, NULL, delim, 0); - if (*content == NULL) - ret = errno; - if (fclose(f) != 0 && ret == 0) - ret = errno; - return ret; -} - -static int -check_meta_file_exists(const char *worktree_path, const char *name) -{ - struct stat sb; - char *path; - int ret = 0; - - if (asprintf(&path, "%s/%s/%s", worktree_path, GOT_WORKTREE_GOT_DIR, - name) == -1) - return 0; - if (stat(path, &sb) == 0) - ret = 1; - if (verbose) { - char *content; - if (read_meta_file(&content, path) == 0) { - test_printf("%s:\t%s\n", name, content); - free(content); - } - } - free(path); - return ret; -} - -static int -worktree_init(const char *repo_path) -{ - const struct got_error *err; - struct got_repository *repo = NULL; - struct got_reference *head_ref = NULL; - char worktree_path[PATH_MAX]; - int ok = 0; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - goto done; - err = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0); - if (err != NULL || head_ref == NULL) - goto done; - - strlcpy(worktree_path, "worktree-XXXXXX", sizeof(worktree_path)); - if (mkdtemp(worktree_path) == NULL) - goto done; - - err = got_worktree_init(worktree_path, head_ref, "/", repo); - if (err != NULL) - goto done; - - /* Ensure required files were created. */ - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_HEAD_REF)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_BASE_COMMIT)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_LOCK)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_FILE_INDEX)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_REPOSITORY)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_PATH_PREFIX)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_FORMAT)) - goto done; - if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_UUID)) - goto done; - - if (!remove_worktree(worktree_path)) - goto done; - ok = 1; -done: - if (head_ref) - got_ref_close(head_ref); - if (repo) - got_repo_close(repo); - return ok; -} - -static int -obstruct_meta_file(char **path, const char *worktree_path, const char *name) -{ - FILE *f; - char *s = "This file should not be here\n"; - int ret = 1; - - if (asprintf(path, "%s/%s/%s", worktree_path, GOT_WORKTREE_GOT_DIR, - name) == -1) - return 0; - f = fopen(*path, "w+"); - if (f == NULL) { - free(*path); - return 0; - } - if (fwrite(s, 1, strlen(s), f) != strlen(s)) { - free(*path); - ret = 0; - } - if (fclose(f) != 0) - ret = 0; - return ret; -} - -static int -obstruct_meta_file_and_init(int *ok, struct got_repository *repo, - const char *worktree_path, char *name) -{ - const struct got_error *err; - char *path; - int ret = 0; - struct got_reference *head_ref = NULL; - - if (!obstruct_meta_file(&path, worktree_path, GOT_WORKTREE_FILE_INDEX)) - return 0; - - err = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0); - if (err != NULL || head_ref == NULL) - return 0; - - err = got_worktree_init(worktree_path, head_ref, "/", repo); - if (err != NULL && err->code == GOT_ERR_ERRNO && errno == EEXIST) { - (*ok)++; - ret = 1; - } - unlink(path); - free(path); - got_ref_close(head_ref); - return ret; -} - -static int -worktree_init_exists(const char *repo_path) -{ - const struct got_error *err; - struct got_repository *repo = NULL; - char worktree_path[PATH_MAX]; - char *gotpath = NULL; - int ok = 0; - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - goto done; - strlcpy(worktree_path, "worktree-XXXXXX", sizeof(worktree_path)); - if (mkdtemp(worktree_path) == NULL) - goto done; - if (mkdir(worktree_path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) - goto done; - - if (asprintf(&gotpath, "%s/%s", worktree_path, GOT_WORKTREE_GOT_DIR) - == -1) - goto done; - if (mkdir(gotpath, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) - goto done; - - /* Create files which got_worktree_init() will try to create as well. */ - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_HEAD_REF)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_BASE_COMMIT)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_LOCK)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_FILE_INDEX)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_REPOSITORY)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_PATH_PREFIX)) - goto done; - if (!obstruct_meta_file_and_init(&ok, repo, worktree_path, - GOT_WORKTREE_FORMAT)) - goto done; - -done: - if (repo) - got_repo_close(repo); - free(gotpath); - if (ok == 7) - remove_worktree(worktree_path); - return (ok == 7); -} - -static const struct got_error * -progress_cb(void *arg, unsigned char status, const char *path) -{ - return NULL; -} - -static int -worktree_checkout(const char *repo_path) -{ - const struct got_error *err; - struct got_repository *repo = NULL; - struct got_reference *head_ref = NULL; - struct got_worktree *worktree = NULL; - char *makefile_path = NULL, *cfile_path = NULL; - char worktree_path[PATH_MAX]; - int ok = 0; - struct stat sb; - struct got_pathlist_head paths; - - TAILQ_INIT(&paths); - - err = got_repo_open(&repo, repo_path); - if (err != NULL || repo == NULL) - goto done; - err = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0); - if (err != NULL || head_ref == NULL) - goto done; - - strlcpy(worktree_path, "worktree-XXXXXX", sizeof(worktree_path)); - if (mkdtemp(worktree_path) == NULL) - goto done; - - err = got_worktree_init(worktree_path, head_ref, "/regress/worktree", - repo); - if (err != NULL) - goto done; - - err = got_worktree_open(&worktree, worktree_path); - if (err != NULL) - goto done; - - err = got_pathlist_append(&paths, "", NULL); - if (err) - goto done; - err = got_worktree_checkout_files(worktree, &paths, repo, progress_cb, - NULL, NULL, NULL); - if (err != NULL) - goto done; - - test_printf("checked out %s\n", worktree_path); - - /* The work tree should contain a Makefile and worktree_test.c. */ - if (asprintf(&makefile_path, "%s/Makefile", worktree_path) == -1) - goto done; - if (stat(makefile_path, &sb) != 0) - goto done; - else - unlink(makefile_path); - if (asprintf(&cfile_path, "%s/worktree_test.c", worktree_path) == -1) - goto done; - if (stat(cfile_path, &sb) != 0) - goto done; - else - unlink(cfile_path); - - err = remove_worktree_base_ref(worktree, repo); - if (err) - goto done; - if (!remove_worktree(worktree_path)) - goto done; - - ok = 1; -done: - if (worktree) - got_worktree_close(worktree); - if (head_ref) - got_ref_close(head_ref); - if (repo) - got_repo_close(repo); - got_pathlist_free(&paths); - free(makefile_path); - free(cfile_path); - return ok; -} - -#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: worktree_test [-v] [REPO_PATH]\n"); -} - -int -main(int argc, char *argv[]) -{ - int test_ok = 0, failure = 0; - const char *repo_path; - char *cwd = NULL; - int ch; - -#ifndef PROFILE - if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd " - "unveil", 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; - - if (argc == 0) - repo_path = GOT_REPO_PATH; - else if (argc == 1) - repo_path = argv[0]; - else { - usage(); - return 1; - } - - cwd = getcwd(NULL, 0); - if (cwd == NULL) - err(1, "getcwd"); - if (unveil(cwd, "rwc") != 0) - err(1, "unvail"); - free(cwd); - - if (unveil("/tmp", "rwc") != 0) - err(1, "unveil"); - - if (unveil(repo_path, "rwc") != 0) - err(1, "unveil"); - - if (got_privsep_unveil_exec_helpers() != NULL) - return 1; - - if (unveil(NULL, NULL) != 0) - err(1, "unveil"); - - RUN_TEST(worktree_init(repo_path), "init"); - RUN_TEST(worktree_init_exists(repo_path), "init exists"); - RUN_TEST(worktree_checkout(repo_path), "checkout"); - - return failure ? 1 : 0; -}