Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package-lock.json
clib-build
clib-update
clib-upgrade
clib-uninstall

test/package/package-*
!test/package/package-*.c
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CC ?= cc
PREFIX ?= /usr/local

BINS = clib clib-install clib-search clib-init clib-configure clib-build clib-update clib-upgrade
BINS = clib clib-install clib-search clib-init clib-configure clib-build clib-update clib-upgrade clib-uninstall

ifdef EXE
BINS := $(addsuffix .exe,$(BINS))
Expand Down
2 changes: 1 addition & 1 deletion deps/http-get/clib.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "http-get",
"version": "0.3.0",
"version": "0.4.0",
"repo": "clibs/http-get.c",
"description": "Simple HTTP GET requests backed by libcurl",
"keywords": [
Expand Down
6 changes: 2 additions & 4 deletions deps/http-get/http-get.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
#ifndef HTTP_GET_H
#define HTTP_GET_H 1

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <unistd.h>
#endif
#include <stdlib.h>

#define HTTP_GET_VERSION "0.3.0"
#define HTTP_GET_VERSION "0.4.0"

typedef struct {
char *data;
Expand Down
212 changes: 212 additions & 0 deletions src/clib-uninstall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
//
// clib-uninstall.c
//
// Copyright (c) 2014 Stephen Mathieson
// Copyright (c) 2021 clib authors
//
// MIT licensed
//

#include "asprintf/asprintf.h"
#include "commander/commander.h"
#include "http-get/http-get.h"
#include "logger/logger.h"
#include "parse-repo/parse-repo.h"
#include "debug/debug.h"
#include "parson/parson.h"
#include "version.h"
#include <stdlib.h>
#include <string.h>

#define CLIB_UNINSTALL_DEFAULT_TARGET "make uninstall"

#if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || \
defined(__MINGW64__) || defined(__CYGWIN__)
#define setenv(k, v, _) _putenv_s(k, v)
#endif

debug_t debugger;

static void setopt_prefix(command_t *self) {
setenv("PREFIX", (char *)self->arg, 1);
debug(&debugger, "set prefix: %s", (char *)self->arg);
}

static char *get_tarball_url(const char *owner, const char *name,
const char *version) {
char *tarball = NULL;
int size = 0;

size = asprintf(&tarball, "https://github.com/%s/%s/archive/%s.tar.gz", owner,
name, version);

if (-1 == size)
return NULL;
return tarball;
}

static char *get_tar_filepath(const char *name, const char *version) {
char *file = NULL;
int size = asprintf(&file, "%s-%s.tar.gz", name, version);
if (-1 == size)
return NULL;
return file;
}

static char *get_tmp_tarball(const char *file) {
char *tmp = NULL;
int size = asprintf(&tmp, "/tmp/%s", file);
if (-1 == size)
return NULL;
return tmp;
}

static char *get_untar_command(const char *file) {
char *cmd = NULL;
int size = 0;
size = asprintf(&cmd, "cd /tmp && tar -xf %s", file);
if (-1 == size)
return NULL;
return cmd;
}

static char *get_uninstall_target(const char *name, const char *version) {
int size = 0;
char *target = NULL;
char *dir = NULL;
char *pkg = NULL;
const char *val = NULL;
JSON_Value *root = NULL;
JSON_Object *obj = NULL;

size = asprintf(&dir, "/tmp/%s-%s", name, version);
if (-1 == size)
return NULL;

size = asprintf(&pkg, "%s/package.json", dir);
if (-1 == size)
goto done;

root = json_parse_file(pkg);
if (!root)
goto done;

obj = json_value_get_object(root);
if (!obj)
goto done;

val = json_object_get_string(obj, "uninstall");
if (!val) {
logger_warn("warning",
"No uninstall target specified. Defaulting to '%s'.",
CLIB_UNINSTALL_DEFAULT_TARGET);
// default to "make uninstall"
val = CLIB_UNINSTALL_DEFAULT_TARGET;
}

size = asprintf(&target, "cd %s && %s", dir, val);
if (-1 == size)
return NULL;

done:
if (root)
json_value_free(root);
free(dir);
free(pkg);
return target;
}

static int clib_uninstall(const char *owner, const char *name,
const char *version) {
char *tarball = NULL;
char *file = NULL;
char *tarpath = NULL;
char *cmd = NULL;
char *target = NULL;
int rc = -1;

// sanity
if (!owner || !name || !version)
return -1;

if (!(tarball = get_tarball_url(owner, name, version)))
goto done;
if (!(file = get_tar_filepath(name, version)))
goto done;
if (!(tarpath = get_tmp_tarball(file)))
goto done;

logger_info("fetch", tarball);
if (-1 == http_get_file(tarball, tarpath)) {
logger_error("error", "failed to fetch tarball");
goto done;
}

if (!(cmd = get_untar_command(file)))
goto done;

logger_info("untar", tarpath);
if (0 != system(cmd)) {
logger_error("error", "failed to untar");
goto done;
}

target = get_uninstall_target(name, version);
if (!target)
goto done;

rc = system(target);

done:
free(tarball);
free(file);
free(tarpath);
free(cmd);
free(target);
return rc;
}

int main(int argc, char **argv) {
int rc = 1;
command_t program;

debug_init(&debugger, "clib-uninstall");

command_init(&program, "clib-uninstall", CLIB_VERSION);

program.usage = "[options] [name ...]";

command_option(&program, "-P", "--prefix <dir>",
"change the prefix directory (usually '/usr/local')",
setopt_prefix);

command_parse(&program, argc, argv);

if (0 == program.argc)
command_help(&program);

for (int i = 0; i < program.argc; i++) {
char *owner = parse_repo_owner(program.argv[i], NULL);
if (!owner)
goto cleanup;
char *name = parse_repo_name(program.argv[i]);
if (!name) {
free(owner);
goto cleanup;
}

int res = clib_uninstall(owner, name, "master");
free(owner);
free(name);
if (-1 == res) {
logger_error("error", "Failed to uninstall %s", program.argv[i]);
goto cleanup;
}
}

rc = 0;

cleanup:
command_free(&program);
return rc;
}
1 change: 1 addition & 0 deletions src/clib.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static const char *usage =
" init Start a new project\n"
" i, install [name...] Install one or more packages\n"
" up, update [name...] Update one or more packages\n"
" uninstall [name...] Uninstall executables\n"
" upgrade [version] Upgrade clib to a specified or latest version\n"
" configure [name...] Configure one or more packages\n"
" build [name...] Build one or more packages\n"
Expand Down
18 changes: 18 additions & 0 deletions test/uninstall.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

mkdir -p tmp/bin

clib install -c stephenmathieson/[email protected] -P tmp > /dev/null || {
echo >&2 "Failed to install stephenmathieson/tabs-to-spaces"
exit 1
}

clib uninstall stephenmathieson/tabs-to-spaces -P tmp

# ensure the un-installation worked
command -v tmp/bin/t2s >/dev/null 2>&1 && {
exit 0
}

echo >&2 "Failed to uninstall stephenmathieson/tabs-to-spaces";
exit 1