Initial checkin 0.1
authorJ. Ali Harlow <ali@juiblex.co.uk>
Thu, 9 Jul 2009 07:23:50 +0000 (08:23 +0100)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Thu, 9 Jul 2009 07:23:50 +0000 (08:23 +0100)
17 files changed:
.gitignore [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
bootstrap.sh [new file with mode: 0644]
configure.ac [new file with mode: 0644]
plover/Makefile.am [new file with mode: 0644]
plover/comps.c [new file with mode: 0644]
plover/import-yum.c [new file with mode: 0644]
plover/plover.h [new file with mode: 0644]
plover/plover.pc.in [new file with mode: 0644]
plover/razor.c [new file with mode: 0644]
plover/util.c [new file with mode: 0644]
setup/Makefile.am [new file with mode: 0644]
setup/icon16.png [new file with mode: 0644]
setup/icon22.png [new file with mode: 0644]
setup/icon32.png [new file with mode: 0644]
setup/resources.rc.in [new file with mode: 0644]
setup/setup.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4eedacf
--- /dev/null
@@ -0,0 +1,18 @@
+Makefile
+Makefile.in
+aclocal.m4
+config.*
+config/
+autom4te.cache/
+configure
+libtool
+plover-*.tar.gz
+stamp-h1
+.deps/
+.libs/
+*.o
+*.lo
+*.la
+plover/plover.pc
+setup/resources.rc
+setup/setup
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..8932f06
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS=plover setup
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100644 (file)
index 0000000..69c3355
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+mkdir -p config
+autoheader
+aclocal
+libtoolize
+automake --foreign --add-missing
+autoconf
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..192455f
--- /dev/null
@@ -0,0 +1,87 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_INIT([plover],[0.1],[ali@juiblex.co.uk])
+AC_PREREQ(2.59)
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_SRCDIR([plover/plover.h])
+AC_CONFIG_HEADER([config.h])
+AC_CONFIG_FILES([Makefile
+plover/Makefile
+plover/plover.pc
+setup/Makefile
+setup/resources.rc
+])
+AM_INIT_AUTOMAKE(no-define)
+case $VERSION in
+  *.*.*)
+    AC_SUBST(PLOVER_MAJOR_VERSION,[[`echo $VERSION | sed 's/\..*//'`]])
+    AC_SUBST(PLOVER_MINOR_VERSION,
+      [[`echo $VERSION | sed 's/[^.]*\.\([^.]*\)\..*/\1/'`]])
+    AC_SUBST(PLOVER_MICRO_VERSION,[[`echo $VERSION | sed 's/.*\.\([^.]*\)/\1/'`]])      ;;
+  *.*)
+    AC_SUBST(PLOVER_MAJOR_VERSION,[[`echo $VERSION | sed 's/\..*//'`]])
+    AC_SUBST(PLOVER_MINOR_VERSION,
+      [[`echo $VERSION | sed 's/[^.]*\.\([^.]*\)/\1/'`]])
+    AC_SUBST(PLOVER_MICRO_VERSION,0)
+    ;;
+  *)
+    AC_SUBST(PLOVER_MAJOR_VERSION,0)
+    AC_SUBST(PLOVER_MINOR_VERSION,0)
+    AC_SUBST(PLOVER_MICRO_VERSION,0)
+    ;;
+esac
+
+##################################################
+# Checks for programs.
+##################################################
+AC_PROG_CC
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+PKG_PROG_PKG_CONFIG
+AC_CHECK_TOOL(WINDRES,windres,no)
+AM_CONDITIONAL([HAVE_WINDRES],[test x$WINDRES != xno])
+
+##################################################
+# Checks for header files.
+##################################################
+AC_HEADER_STDC
+
+##################################################
+# Checks for typedefs, structures, and compiler characteristics.
+##################################################
+
+##################################################
+# Checks for libraries.
+##################################################
+PKG_CHECK_MODULES(RAZOR,[razor],[:],[RAZOR_LIBS=-lrazor])
+PKG_CHECK_MODULES(EXPAT,[expat],[:],[EXPAT_LIBS=-lexpat])
+PKG_CHECK_MODULES(ZLIB,[zlib],[:],[ZLIB_LIBS=-lz])
+LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS"
+LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS"
+AC_SUBST(LIBPLOVER_CFLAGS)
+AC_SUBST(LIBPLOVER_LIBS)
+save_PKG_CONFIG="$PKG_CONFIG"
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES(SETUP,[whelk])
+PKG_CONFIG="$save_PKG_CONFIG"
+save_LIBS="$LIBS"
+AC_SEARCH_LIBS([crypt],[crypt])
+SETUP_LIBS="$SETUP_LIBS $RAZOR_LIBS -llua-posix $LIBS"
+SETUP_CFLAGS="$SETUP_CFLAGS $RAZOR_CFLAGS"
+AC_SUBST(SETUP_LIBS)
+AC_SUBST(SETUP_CFLAGS)
+LIBS="$save_LIBS"
+
+##################################################
+# Checks for library functions.
+##################################################
+
+##################################################
+# Checks for processor independent files.
+##################################################
+
+##################################################
+# Generate the various configured files
+##################################################
+AC_OUTPUT
diff --git a/plover/Makefile.am b/plover/Makefile.am
new file mode 100644 (file)
index 0000000..075dbd8
--- /dev/null
@@ -0,0 +1,12 @@
+AM_CFLAGS=-g $(LIBPLOVER_CFLAGS)
+LIBS=$(LIBPLOVER_LIBS)
+INCLUDES=-I$(top_srcdir)
+LDFLAGS=-no-undefined
+
+lib_LTLIBRARIES=libplover.la
+libplover_la_SOURCES=plover.h util.c import-yum.c razor.c comps.c
+
+pkginclude_HEADERS=plover.h
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=plover.pc
diff --git a/plover/comps.c b/plover/comps.c
new file mode 100644 (file)
index 0000000..cdf7b4c
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <expat.h>
+#include <assert.h>
+#include "plover/plover.h"
+
+/* Parse a comps.xml package group file. */
+
+static struct comps_requirement *comps_package_requirement_new(void)
+{
+    struct comps_requirement *req;
+    req=calloc(sizeof(*req),1);
+    assert(req != NULL);
+    req->type=COMPS_REQUIREMENT_OPTIONAL;
+    return req;
+}
+
+static void comps_package_requirement_free_1(struct comps_requirement *req)
+{
+    if (req)
+    {
+       free(req->requires);
+       free(req->name);
+       free(req);
+    }
+}
+
+static void comps_package_requirement_free(struct comps_requirement *req)
+{
+    struct comps_requirement *next;
+    while(req)
+    {
+       next=req->next;
+       comps_package_requirement_free_1(req);
+       req=next;
+    }
+}
+
+struct comps_group *comps_group_new(void)
+{
+    struct comps_group *group;
+    group=calloc(sizeof(*group),1);
+    assert(group != NULL);
+    group->bydefault=1;
+    group->uservisible=1;
+    return group;
+}
+
+static void comps_group_free_1(struct comps_group *group)
+{
+    if (group)
+    {
+       free(group->id);
+       free(group->name);
+       free(group->description);
+       comps_package_requirement_free(group->packages);
+       free(group);
+    }
+}
+static void comps_group_free(struct comps_group *group)
+{
+    struct comps_group *next;
+    while(group)
+    {
+       next=group->next;
+       comps_group_free_1(group);
+       group=next;
+    }
+}
+
+struct comps *plover_comps_new(void)
+{
+    struct comps *comps;
+    comps=calloc(sizeof(*comps),1);
+    assert(comps != NULL);
+    return comps;
+}
+
+void plover_comps_free(struct comps *comps)
+{
+    if (comps)
+    {
+       free(comps->vendor);
+       comps_group_free(comps->groups);
+       free(comps);
+    }
+}
+
+enum comps_state {
+    COMPS_STATE_BEGIN,
+    COMPS_STATE_ROOT,
+    COMPS_STATE_GROUP,
+    COMPS_STATE_GROUP_ID,
+    COMPS_STATE_GROUP_NAME,
+    COMPS_STATE_GROUP_DESCRIPTION,
+    COMPS_STATE_GROUP_DEFAULT,
+    COMPS_STATE_GROUP_USERVISIBLE,
+    COMPS_STATE_GROUP_PACKAGELIST,
+    COMPS_STATE_GROUP_PACKAGELIST_REQ,
+};
+
+struct comps_context {
+    XML_Parser parser;
+    enum comps_state state;
+    int unknown_elements;
+    char *vendor;
+    struct comps_group *group;
+    void *p;
+};
+
+static enum comps_requirement_type comps_to_requirement_type(const char *flags)
+{
+    if (strcmp(flags, "conditional") == 0)
+       return COMPS_REQUIREMENT_CONDITIONAL;
+    else if (strcmp(flags, "mandatory") == 0)
+       return COMPS_REQUIREMENT_MANDATORY;
+    else if (strcmp(flags, "default") == 0)
+       return COMPS_REQUIREMENT_DEFAULT;
+    else
+       return COMPS_REQUIREMENT_OPTIONAL;
+}
+
+static void comps_start_element(void *data,const char *name,const char **atts)
+{
+    struct comps_context *ctx = data;
+    struct comps_group *group;
+    struct comps_requirement *packages;
+    int i;
+#if 0
+    fprintf(stderr,"Starting element '");
+    switch(ctx->state)
+    {
+       case COMPS_STATE_BEGIN:
+           fprintf(stderr,"/");
+           break;
+       case COMPS_STATE_ROOT:
+           fprintf(stderr,"/comps/");
+           break;
+       case COMPS_STATE_GROUP:
+           fprintf(stderr,"/comps/group/");
+           break;
+       case COMPS_STATE_GROUP_ID:
+           fprintf(stderr,"/comps/group/id/");
+           break;
+       case COMPS_STATE_GROUP_NAME:
+           fprintf(stderr,"/comps/group/name/");
+           break;
+       case COMPS_STATE_GROUP_DESCRIPTION:
+           fprintf(stderr,"/comps/group/description/");
+           break;
+       case COMPS_STATE_GROUP_DEFAULT:
+           fprintf(stderr,"/comps/group/default/");
+           break;
+       case COMPS_STATE_GROUP_USERVISIBLE:
+           fprintf(stderr,"/comps/group/uservisible/");
+           break;
+       case COMPS_STATE_GROUP_PACKAGELIST:
+           fprintf(stderr,"/comps/group/packagelist/");
+           break;
+       case COMPS_STATE_GROUP_PACKAGELIST_REQ:
+           fprintf(stderr,"/comps/group/packagelist/packagereq/");
+           break;
+
+    }
+    for(i=0;i<ctx->unknown_elements;i++)
+       fprintf(stderr,"*/");
+    fprintf(stderr,"%s'\n",name);
+#endif
+    if (ctx->unknown_elements)
+       ctx->unknown_elements++;
+    else if (ctx->state==COMPS_STATE_BEGIN && !strcmp(name,"comps"))
+    {
+       ctx->state=COMPS_STATE_ROOT;
+       for (i=0;atts[i];i+=2)
+       {
+           if (!strcmp(atts[i],
+             "http://project.juiblex.co.uk/plover/ns/2009\xFFvendor"))
+               ctx->vendor=strdup(atts[i+1]);
+       }
+    }
+    else if (ctx->state==COMPS_STATE_ROOT && !strcmp(name,"group"))
+    {
+       ctx->state=COMPS_STATE_GROUP;
+       group=comps_group_new();
+       group->next=ctx->group;
+       ctx->group=group;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"id"))
+    {
+       ctx->state=COMPS_STATE_GROUP_ID;
+       ctx->p=&ctx->group->id;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"name"))
+    {
+       ctx->state=COMPS_STATE_GROUP_NAME;
+       ctx->p=&ctx->group->name;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"description"))
+    {
+       ctx->state=COMPS_STATE_GROUP_DESCRIPTION;
+       ctx->p=&ctx->group->description;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"default"))
+    {
+       ctx->state=COMPS_STATE_GROUP_DEFAULT;
+       ctx->p=&ctx->group->bydefault;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"uservisible"))
+    {
+       ctx->state=COMPS_STATE_GROUP_USERVISIBLE;
+       ctx->p=&ctx->group->uservisible;
+    }
+    else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"packagelist"))
+       ctx->state=COMPS_STATE_GROUP_PACKAGELIST;
+    else if (ctx->state==COMPS_STATE_GROUP_PACKAGELIST &&
+      !strcmp(name,"packagereq"))
+    {
+       packages=comps_package_requirement_new();
+       packages->next=ctx->group->packages;
+       ctx->group->packages=packages;
+       for (i=0;atts[i];i+=2)
+       {
+           if (!strcmp(atts[i],"type"))
+               packages->type=comps_to_requirement_type(atts[i+1]);
+           else if (!strcmp(atts[i],"requires"))
+           {
+               packages->requires=strdup(atts[i+1]);
+               packages->type=COMPS_REQUIREMENT_CONDITIONAL;
+           }
+       }
+       ctx->state=COMPS_STATE_GROUP_PACKAGELIST_REQ;
+       ctx->p=&packages->name;
+    }
+    else
+       ctx->unknown_elements++;
+}
+
+struct comps_list
+{
+    struct comps_list *next;
+    /* body */
+};
+
+void *comps_list_reverse(void *list)
+{
+    struct comps_list *link=list,*prev=NULL,*next;
+    while(link)
+    {
+       next=link->next;
+       link->next=prev;
+       prev=link;
+       link=next;
+    }
+    return prev;
+}
+
+static void comps_end_element(void *data,const char *name)
+{
+    struct comps_context *ctx=data;
+    if (ctx->unknown_elements)
+       ctx->unknown_elements--;
+    else
+       switch (ctx->state)
+       {
+           case COMPS_STATE_ROOT:
+               ctx->group=comps_list_reverse(ctx->group);
+               ctx->state=COMPS_STATE_BEGIN;
+               break;
+           case COMPS_STATE_GROUP:
+               ctx->group->packages=comps_list_reverse(ctx->group->packages);
+               ctx->state=COMPS_STATE_ROOT;
+               break;
+           case COMPS_STATE_GROUP_ID:
+           case COMPS_STATE_GROUP_NAME:
+           case COMPS_STATE_GROUP_DESCRIPTION:
+           case COMPS_STATE_GROUP_DEFAULT:
+           case COMPS_STATE_GROUP_USERVISIBLE:
+           case COMPS_STATE_GROUP_PACKAGELIST:
+               ctx->state=COMPS_STATE_GROUP;
+               break;
+           case COMPS_STATE_GROUP_PACKAGELIST_REQ:
+               ctx->state=COMPS_STATE_GROUP_PACKAGELIST;
+               break;
+       }
+#if 0
+    fprintf(stderr,"Ending element '");
+    switch(ctx->state)
+    {
+       case COMPS_STATE_BEGIN:
+           fprintf(stderr,"/");
+           break;
+       case COMPS_STATE_ROOT:
+           fprintf(stderr,"/comps/");
+           break;
+       case COMPS_STATE_GROUP:
+           fprintf(stderr,"/comps/group/");
+           break;
+       case COMPS_STATE_GROUP_ID:
+           fprintf(stderr,"/comps/group/id/");
+           break;
+       case COMPS_STATE_GROUP_NAME:
+           fprintf(stderr,"/comps/group/name/");
+           break;
+       case COMPS_STATE_GROUP_DESCRIPTION:
+           fprintf(stderr,"/comps/group/description/");
+           break;
+       case COMPS_STATE_GROUP_DEFAULT:
+           fprintf(stderr,"/comps/group/default/");
+           break;
+       case COMPS_STATE_GROUP_USERVISIBLE:
+           fprintf(stderr,"/comps/group/uservisible/");
+           break;
+       case COMPS_STATE_GROUP_PACKAGELIST:
+           fprintf(stderr,"/comps/group/packagelist/");
+           break;
+       case COMPS_STATE_GROUP_PACKAGELIST_REQ:
+           fprintf(stderr,"/comps/group/packagelist/packagereq/");
+           break;
+
+    }
+    {
+       int i;
+       for(i=0;i<ctx->unknown_elements;i++)
+           fprintf(stderr,"*/");
+    }
+    fprintf(stderr,"%s'\n",name);
+#endif
+}
+
+static void comps_character_data(void *data,const XML_Char *s,int len)
+{
+    struct comps_context *ctx=data;
+    char *str;
+    switch (ctx->state)
+    {
+       case COMPS_STATE_GROUP_ID:
+       case COMPS_STATE_GROUP_NAME:
+       case COMPS_STATE_GROUP_DESCRIPTION:
+       case COMPS_STATE_GROUP_PACKAGELIST_REQ:
+           *(char **)ctx->p=str=malloc(len+1);
+           memcpy(str,s,len);
+           str[len]='\0';
+           break;
+       case COMPS_STATE_GROUP_DEFAULT:
+       case COMPS_STATE_GROUP_USERVISIBLE:
+           *(int *)ctx->p=*s=='T'||*s=='t';
+           break;
+    }
+}
+
+#define XML_BUFFER_SIZE 4096
+
+struct comps *plover_comps_new_from_file(const char *filename)
+{
+    struct comps_context ctx={0};
+    void *buf;
+    int len;
+    FILE *fp;
+    XML_ParsingStatus status;
+    struct comps *comps;
+    fp=fopen(filename,"r");
+    if (!fp)
+       return NULL;
+    ctx.state=COMPS_STATE_BEGIN;
+    ctx.parser=XML_ParserCreateNS(NULL,'\xFF');
+    XML_SetUserData(ctx.parser,&ctx);
+    XML_SetElementHandler(ctx.parser,comps_start_element,comps_end_element);
+    XML_SetCharacterDataHandler(ctx.parser,comps_character_data);
+    do
+    {
+       XML_GetParsingStatus(ctx.parser,&status);
+       switch (status.parsing)
+       {
+           case XML_SUSPENDED:
+               XML_ResumeParser(ctx.parser);
+               break;
+           case XML_PARSING:
+           case XML_INITIALIZED:
+               buf=XML_GetBuffer(ctx.parser,XML_BUFFER_SIZE);
+               len=fread(buf,1,XML_BUFFER_SIZE,fp);
+               if (len<0)
+               {
+                   comps_group_free(ctx.group);
+                   XML_ParserFree(ctx.parser);
+                   fclose(fp);
+                   return NULL;
+               }
+               if (!XML_ParseBuffer(ctx.parser,len,!len))
+               {
+                   comps_group_free(ctx.group);
+                   XML_ParserFree(ctx.parser);
+                   fclose(fp);
+                   return NULL;
+               }
+               break;
+           case XML_FINISHED:
+               break;
+       }
+    } while (status.parsing!=XML_FINISHED);
+    XML_ParserFree(ctx.parser);
+    fclose(fp);
+    comps=plover_comps_new();
+    comps->vendor=ctx.vendor;
+    comps->groups=ctx.group;
+    return comps;
+}
+
+struct comps_group *plover_comps_lookup_group(struct comps *comps,
+  const char *id)
+{
+    struct comps_group *group;
+    for(group=comps->groups;group;group=group->next)
+       if (!strcmp(group->id,id))
+           return group;
+    return NULL;
+}
diff --git a/plover/import-yum.c b/plover/import-yum.c
new file mode 100644 (file)
index 0000000..d6c0c5e
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <expat.h>
+#include <zlib.h>
+#include <razor.h>
+#include "plover.h"
+
+/* Import a yum filelist as a razor package set. */
+
+enum {
+       YUM_STATE_BEGIN,
+       YUM_STATE_PACKAGE_NAME,
+       YUM_STATE_PACKAGE_ARCH,
+       YUM_STATE_SUMMARY,
+       YUM_STATE_DESCRIPTION,
+       YUM_STATE_URL,
+       YUM_STATE_LICENSE,
+       YUM_STATE_CHECKSUM,
+       YUM_STATE_REQUIRES,
+       YUM_STATE_PROVIDES,
+       YUM_STATE_OBSOLETES,
+       YUM_STATE_CONFLICTS,
+       YUM_STATE_FILE
+};
+
+struct yum_context {
+       XML_Parser primary_parser;
+       XML_Parser filelists_parser;
+       XML_Parser current_parser;
+
+       struct razor_importer *importer;
+       struct import_property_context *current_property_context;
+       char name[256], arch[64], summary[512], description[4096];
+       char url[256], license[64], buffer[512], *p;
+       char pkgid[128];
+       uint32_t property_type;
+       int state;
+
+       int total, current;
+};
+
+static uint32_t
+yum_to_razor_relation (const char *flags)
+{
+       if (flags[0] == 'L') {
+               if (flags[1] == 'T')
+                       return RAZOR_PROPERTY_LESS;
+               else
+                       return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
+       } else if (flags[0] == 'G') {
+               if (flags[1] == 'T')
+                       return RAZOR_PROPERTY_GREATER;
+               else
+                       return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
+       } else
+               return RAZOR_PROPERTY_EQUAL;
+}
+
+static void
+yum_primary_start_element(void *data, const char *name, const char **atts)
+{
+       struct yum_context *ctx = data;
+       const char *n, *epoch, *version, *release;
+       char buffer[128];
+       uint32_t pre, relation, flags;
+       int i;
+
+       if (strcmp(name, "metadata") == 0) {
+               for (i = 0; atts[i]; i += 2) {
+                       if (strcmp(atts[i], "packages") == 0)
+                               ctx->total = atoi(atts[i + 1]);
+               }
+       } else if (strcmp(name, "name") == 0) {
+               ctx->state = YUM_STATE_PACKAGE_NAME;
+               ctx->p = ctx->name;
+       } else if (strcmp(name, "arch") == 0) {
+               ctx->state = YUM_STATE_PACKAGE_ARCH;
+               ctx->p = ctx->arch;
+       } else if (strcmp(name, "version") == 0) {
+               epoch = NULL;
+               version = NULL;
+               release = NULL;
+               for (i = 0; atts[i]; i += 2) {
+                       if (strcmp(atts[i], "epoch") == 0)
+                               epoch = atts[i + 1];
+                       else if (strcmp(atts[i], "ver") == 0)
+                               version = atts[i + 1];
+                       else if (strcmp(atts[i], "rel") == 0)
+                               release = atts[i + 1];
+               }
+               if (version == NULL || release == NULL) {
+                       fprintf(stderr, "invalid version tag, "
+                               "missing version or  release attribute\n");
+                       return;
+               }
+
+               razor_build_evr(buffer, sizeof buffer, epoch, version, release);
+               razor_importer_begin_package(ctx->importer,
+                                            ctx->name, buffer, ctx->arch);
+       } else if (strcmp(name, "summary") == 0) {
+               ctx->p = ctx->summary;
+               ctx->state = YUM_STATE_SUMMARY;
+       } else if (strcmp(name, "description") == 0) {
+               ctx->p = ctx->description;
+               ctx->state = YUM_STATE_DESCRIPTION;
+       } else if (strcmp(name, "url") == 0) {
+               ctx->p = ctx->url;
+               ctx->state = YUM_STATE_URL;
+       } else if (strcmp(name, "checksum") == 0) {
+               ctx->p = ctx->pkgid;
+               ctx->state = YUM_STATE_CHECKSUM;
+       } else if (strcmp(name, "rpm:license") == 0) {
+               ctx->p = ctx->license;
+               ctx->state = YUM_STATE_LICENSE;
+       } else if (strcmp(name, "rpm:requires") == 0) {
+               ctx->state = YUM_STATE_REQUIRES;
+               ctx->property_type = RAZOR_PROPERTY_REQUIRES;
+       } else if (strcmp(name, "rpm:provides") == 0) {
+               ctx->state = YUM_STATE_PROVIDES;
+               ctx->property_type = RAZOR_PROPERTY_PROVIDES;
+       } else if (strcmp(name, "rpm:obsoletes") == 0) {
+               ctx->state = YUM_STATE_OBSOLETES;
+               ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
+       } else if (strcmp(name, "rpm:conflicts") == 0) {
+               ctx->state = YUM_STATE_CONFLICTS;
+               ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
+       } else if (strcmp(name, "rpm:entry") == 0 &&
+                  ctx->state != YUM_STATE_BEGIN) {
+               n = NULL;
+               epoch = NULL;
+               version = NULL;
+               release = NULL;
+               relation = RAZOR_PROPERTY_EQUAL;
+               pre = 0;
+               for (i = 0; atts[i]; i += 2) {
+                       if (strcmp(atts[i], "name") == 0)
+                               n = atts[i + 1];
+                       else if (strcmp(atts[i], "epoch") == 0)
+                               epoch = atts[i + 1];
+                       else if (strcmp(atts[i], "ver") == 0)
+                               version = atts[i + 1];
+                       else if (strcmp(atts[i], "rel") == 0)
+                               release = atts[i + 1];
+                       else if (strcmp(atts[i], "flags") == 0)
+                               relation = yum_to_razor_relation(atts[i + 1]);
+                       else if (strcmp(atts[i], "pre") == 0)
+                               pre =
+                                       RAZOR_PROPERTY_PRE |
+                                       RAZOR_PROPERTY_POST |
+                                       RAZOR_PROPERTY_PREUN |
+                                       RAZOR_PROPERTY_POSTUN;
+               }
+
+               if (n == NULL) {
+                       fprintf(stderr, "invalid rpm:entry, "
+                               "missing name or version attributes\n");
+                       return;
+               }
+
+               razor_build_evr(buffer, sizeof buffer, epoch, version, release);
+               flags = ctx->property_type | relation | pre;
+               razor_importer_add_property(ctx->importer, n, flags, buffer);
+       }
+}
+
+static void
+yum_primary_end_element (void *data, const char *name)
+{
+       struct yum_context *ctx = data;
+
+       switch (ctx->state) {
+       case YUM_STATE_PACKAGE_NAME:
+       case YUM_STATE_PACKAGE_ARCH:
+       case YUM_STATE_SUMMARY:
+       case YUM_STATE_DESCRIPTION:
+       case YUM_STATE_URL:
+       case YUM_STATE_LICENSE:
+       case YUM_STATE_CHECKSUM:
+       case YUM_STATE_FILE:
+               ctx->state = YUM_STATE_BEGIN;
+               break;
+       }
+
+       if (strcmp(name, "package") == 0) {
+               razor_importer_add_details(ctx->importer, ctx->summary,
+                                          ctx->description, ctx->url,
+                                          ctx->license);
+
+               XML_StopParser(ctx->current_parser, XML_TRUE);
+               ctx->current_parser = ctx->filelists_parser;
+
+               printf("\rimporting %d/%d", ++ctx->current, ctx->total);
+               fflush(stdout);
+       }
+}
+
+static void
+yum_character_data (void *data, const XML_Char *s, int len)
+{
+       struct yum_context *ctx = data;
+
+       switch (ctx->state) {
+       case YUM_STATE_PACKAGE_NAME:
+       case YUM_STATE_PACKAGE_ARCH:
+       case YUM_STATE_SUMMARY:
+       case YUM_STATE_DESCRIPTION:
+       case YUM_STATE_URL:
+       case YUM_STATE_LICENSE:
+       case YUM_STATE_CHECKSUM:
+       case YUM_STATE_FILE:
+               memcpy(ctx->p, s, len);
+               ctx->p += len;
+               *ctx->p = '\0';
+               break;
+       }
+}
+
+static void
+yum_filelists_start_element(void *data, const char *name, const char **atts)
+{
+       struct yum_context *ctx = data;
+       const char *pkg, *pkgid;
+       int i;
+
+       if (strcmp(name, "package") == 0) {
+               pkg = NULL;
+               pkgid = NULL;
+               for (i = 0; atts[i]; i += 2) {
+                       if (strcmp(atts[i], "name") == 0)
+                               pkg = atts[i + 1];
+                       else if (strcmp(atts[i], "pkgid") == 0)
+                               pkgid = atts[i + 1];
+               }
+               if (strcmp(pkgid, ctx->pkgid) != 0)
+                       fprintf(stderr, "primary.xml and filelists.xml "
+                               "mismatch for %s: %s vs %s",
+                               pkg, pkgid, ctx->pkgid);
+       } else if (strcmp(name, "file") == 0) {
+               ctx->state = YUM_STATE_FILE;
+               ctx->p = ctx->buffer;
+       }
+}
+
+static void
+yum_filelists_end_element (void *data, const char *name)
+{
+       struct yum_context *ctx = data;
+
+       ctx->state = YUM_STATE_BEGIN;
+       if (strcmp(name, "package") == 0) {
+               XML_StopParser(ctx->current_parser, XML_TRUE);
+               ctx->current_parser = ctx->primary_parser;
+               razor_importer_finish_package(ctx->importer);
+       } else if (strcmp(name, "file") == 0)
+               razor_importer_add_file(ctx->importer, ctx->buffer);
+
+}
+
+#define XML_BUFFER_SIZE 4096
+
+struct razor_set *
+plover_razor_set_create_from_yum(const char *base)
+{
+       struct yum_context ctx;
+       void *buf;
+       int len, ret;
+       gzFile primary, filelists;
+       XML_ParsingStatus status;
+
+       ctx.importer = razor_importer_create();
+       ctx.state = YUM_STATE_BEGIN;
+
+       ctx.primary_parser = XML_ParserCreate(NULL);
+       XML_SetUserData(ctx.primary_parser, &ctx);
+       XML_SetElementHandler(ctx.primary_parser,
+                             yum_primary_start_element,
+                             yum_primary_end_element);
+       XML_SetCharacterDataHandler(ctx.primary_parser,
+                                   yum_character_data);
+
+       ctx.filelists_parser = XML_ParserCreate(NULL);
+       XML_SetUserData(ctx.filelists_parser, &ctx);
+       XML_SetElementHandler(ctx.filelists_parser,
+                             yum_filelists_start_element,
+                             yum_filelists_end_element);
+       XML_SetCharacterDataHandler(ctx.filelists_parser,
+                                   yum_character_data);
+
+       primary = gzopen("primary.xml.gz", "rb");
+       if (primary == NULL)
+               return NULL;
+       filelists = gzopen("filelists.xml.gz", "rb");
+       if (filelists == NULL)
+               return NULL;
+
+       ctx.current_parser = ctx.primary_parser;
+
+       ctx.current = 0;
+
+       do {
+               XML_GetParsingStatus(ctx.current_parser, &status);
+               switch (status.parsing) {
+               case XML_SUSPENDED:
+                       ret = XML_ResumeParser(ctx.current_parser);
+                       break;
+               case XML_PARSING:
+               case XML_INITIALIZED:
+                       buf = XML_GetBuffer(ctx.current_parser,
+                                           XML_BUFFER_SIZE);
+                       if (ctx.current_parser == ctx.primary_parser)
+                               len = gzread(primary, buf, XML_BUFFER_SIZE);
+                       else
+                               len = gzread(filelists, buf, XML_BUFFER_SIZE);
+                       if (len < 0) {
+                               fprintf(stderr,
+                                       "couldn't read input: %s\n",
+                                       strerror(errno));
+                               return NULL;
+                       }
+
+                       XML_ParseBuffer(ctx.current_parser, len, len == 0);
+                       break;
+               case XML_FINISHED:
+                       break;
+               }
+       } while (status.parsing != XML_FINISHED);
+
+
+       XML_ParserFree(ctx.primary_parser);
+       XML_ParserFree(ctx.filelists_parser);
+
+       gzclose(primary);
+       gzclose(filelists);
+
+       printf ("\nsaving\n");
+       return razor_importer_finish(ctx.importer);
+}
diff --git a/plover/plover.h b/plover/plover.h
new file mode 100644 (file)
index 0000000..97d0eeb
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __PLOVER_H__
+#define __PLOVER_H__
+
+#include <razor.h>
+
+enum comps_requirement_type
+{
+    COMPS_REQUIREMENT_OPTIONAL,
+    COMPS_REQUIREMENT_DEFAULT,
+    COMPS_REQUIREMENT_MANDATORY,
+    COMPS_REQUIREMENT_CONDITIONAL
+};
+
+struct comps_requirement
+{
+    struct comps_requirement *next;
+    enum comps_requirement_type type;
+    char *requires;             /* For type == COMPS_REQUIREMENT_CONDITIONAL */
+    char *name;
+};
+
+struct comps_group
+{
+    struct comps_group *next;
+    char *id,*name,*description;
+    int bydefault,uservisible;
+    struct comps_requirement *packages;
+};
+
+struct comps
+{
+    char *vendor;
+    struct comps_group *groups;
+};
+
+char *plover_strconcat(const char *string,...);
+
+struct razor_set *plover_razor_set_create_from_yum(const char *base);
+
+struct razor_set *plover_relocate_packages(struct razor_set *set,
+  const char *base,struct razor_relocations *relocations);
+int plover_run_transaction(struct razor_transaction *trans,const char *base,
+  const char *install_root,struct razor_set *system,struct razor_set *next,
+  struct razor_relocations *relocations);
+int plover_install(const char *base,const char *prefix,char **pkgs);
+int plover_remove(char **pkgs);
+
+struct comps *plover_comps_new(void);
+struct comps *plover_comps_new_from_file(const char *filename);
+void plover_comps_free(struct comps *comps);
+struct comps_group *plover_comps_lookup_group(struct comps *comps,
+  const char *id);
+
+#endif /* __PLOVER_H__ */
diff --git a/plover/plover.pc.in b/plover/plover.pc.in
new file mode 100644 (file)
index 0000000..bab71c3
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: plover
+Description: Plover packaging system
+Version: @VERSION@
+Requires: razor expat zlib
+Libs: -L${libdir} -lplover
+Cflags: -I${includedir}
diff --git a/plover/razor.c b/plover/razor.c
new file mode 100644 (file)
index 0000000..e849a87
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <razor.h>
+#include "config.h"
+#include "plover/plover.h"
+
+static char *rpm_filename(const char *name,const char *version,const char *arch)
+{
+    const char *v;
+    v=strchr(version,':');           /* Skip epoch */
+    if (v)
+       v++;
+    else
+       v=version;
+    return plover_strconcat(name,"-",v,".",arch,".rpm",NULL);
+}
+
+struct razor_set *plover_relocate_packages(struct razor_set *set,
+  const char *base,struct razor_relocations *relocations)
+{
+    struct razor_importer *importer;
+    struct razor_property_iterator *prop_iter;
+    struct razor_package_iterator *pkg_iter;
+    struct razor_file_iterator *file_iter;
+    struct razor_package *package;
+    struct razor_property *property;
+    struct razor_rpm *rpm;
+    const char *name,*version,*arch,*summary,*desc,*url,*license;
+    char *s,*file;
+    uint32_t flags;
+    importer=razor_importer_create();
+    pkg_iter=razor_package_iterator_create(set);
+    while (razor_package_iterator_next(pkg_iter,&package,RAZOR_DETAIL_NAME,
+      &name,RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
+      RAZOR_DETAIL_SUMMARY,&summary,RAZOR_DETAIL_DESCRIPTION,&desc,
+      RAZOR_DETAIL_URL,&url,RAZOR_DETAIL_LICENSE,&license,RAZOR_DETAIL_LAST))
+    {
+       s=rpm_filename(name,version,arch);
+       file=plover_strconcat(base,"/rpms/",s,NULL);
+       free(s);
+       rpm=razor_rpm_open(file);
+       if (!rpm)
+       {
+           fprintf(stderr,"failed to open rpm %s\n",file);
+           razor_package_iterator_destroy(pkg_iter);
+           razor_importer_destroy(importer);
+           free(file);
+           return NULL;
+       }
+       free(file);
+       razor_relocations_set_rpm(relocations,rpm);
+       razor_rpm_close(rpm);
+       razor_importer_begin_package(importer,name,version,arch);
+       razor_importer_add_details(importer,summary,desc,url,license);
+       prop_iter=razor_property_iterator_create(set,package);
+       while (razor_property_iterator_next(prop_iter,&property,&name,&flags,
+         &version))
+           razor_importer_add_property(importer,name,flags,version);
+       razor_property_iterator_destroy(prop_iter);
+       file_iter=razor_file_iterator_create(set,package,0);
+       while (razor_file_iterator_next(file_iter,&name))
+       {
+           name=razor_relocations_apply(relocations,name);
+           razor_importer_add_file(importer,name);
+       }
+       razor_file_iterator_destroy(file_iter);
+       razor_importer_finish_package(importer);
+    }
+    razor_package_iterator_destroy(pkg_iter);
+    return razor_importer_finish(importer);
+}
+
+int plover_run_transaction(struct razor_transaction *trans,const char *base,
+  const char *install_root,struct razor_set *system,struct razor_set *next,
+  struct razor_relocations *relocations)
+{
+    struct razor_install_iterator *ii;
+    struct razor_package *package;
+    struct razor_set *set;
+    enum razor_install_action action;
+    struct razor_rpm *rpm;
+    const char *name,*version,*arch;
+    char *s,*file;
+    int count;
+    ii=razor_set_create_install_iterator(system,next);
+    printf("Running Transaction\n");
+    while (razor_install_iterator_next(ii,&set,&package,&action,&count))
+    {
+       if (action==RAZOR_INSTALL_ACTION_REMOVE)
+       {
+           razor_package_get_details(set,package,RAZOR_DETAIL_NAME,&name,
+             RAZOR_DETAIL_LAST);
+           printf("  Removing : %s ",name);
+           if (razor_package_remove(set,package,install_root,0)<0)
+               printf(
+                 "\nWarning: one or more errors occurred while removing %s",
+                 name);
+           printf("\n");
+       }
+       else
+       {
+           razor_package_get_details(set,package,RAZOR_DETAIL_NAME,&name,
+             RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
+             RAZOR_DETAIL_LAST);
+           printf("  Installing : %s ",name);
+           s=rpm_filename(name,version,arch);
+           file=plover_strconcat(base,"/rpms/",s,NULL);
+           free(s);
+           rpm=razor_rpm_open(file);
+           if (!rpm)
+           {
+               fprintf(stderr,"failed to open rpm %s\n",file);
+               free(file);
+               razor_install_iterator_destroy(ii);
+               return -1;
+           }
+           if (relocations)
+               razor_rpm_set_relocations(rpm,relocations);
+           razor_transaction_fixup_package(trans,package,rpm);
+           if (razor_rpm_install(rpm,install_root,1)<0)
+           {
+               fprintf(stderr,"failed to install rpm %s\n",file);
+               razor_rpm_close(rpm);
+               free(file);
+               razor_install_iterator_destroy(ii);
+               return -1;
+           }
+           razor_rpm_close(rpm);
+           free(file);
+           printf("\n");
+       }
+    }
+    razor_install_iterator_destroy(ii);
+    return 0;
+}
+
+static int plover_mark_package_for_update(struct razor_transaction *trans,
+  struct razor_set *set,const char *pkg)
+{
+    struct razor_package_iterator *pi;
+    struct razor_package *package;
+    const char *name;
+    int retval=-1;
+    pi=razor_package_iterator_create(set);
+    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
+      RAZOR_DETAIL_LAST))
+    {
+       if (!strcmp(name,pkg))
+       {
+           razor_transaction_update_package(trans,package);
+           retval=0;
+           break;
+       }
+    }
+    razor_package_iterator_destroy(pi);
+    return retval;
+}
+
+int plover_install(const char *base,const char *prefix,char **pkgs)
+{
+    int i;
+    char *s;
+    char *install_root;
+    struct razor_root *root;
+    struct razor_set *system,*set,*upstream,*next;
+    struct razor_transaction *trans;
+    struct razor_relocations *relocations;
+    install_root=getenv("RAZOR_ROOT");
+    if (!install_root)
+       install_root="";
+    if (prefix)
+    {
+       relocations=razor_relocations_create();
+       razor_relocations_add(relocations,"/usr",prefix);
+    }
+    /*
+     * Calling razor_root_open() on a system that hasn't yet had
+     * razor_root_create() run generates a confusing error message
+     * on stderr. Avoid this by trying to open it R/O first which
+     * fails without generating any error.
+     */
+    set=razor_root_open_read_only(install_root);
+    if (set)
+       razor_set_destroy(set);
+    else
+       razor_root_create(install_root);
+    root=razor_root_open(install_root);
+    if (!root)
+       return -1;
+    system=razor_root_get_system_set(root);
+    if (!system)
+    {
+       razor_root_close(root);
+       return -1;
+    }
+    s=plover_strconcat(base,"/repodata",NULL);
+    if (!s)
+    {
+       razor_root_close(root);
+       return -1;
+    }
+    if (chdir(s)<0)
+    {
+       perror(s);
+       free(s);
+       razor_root_close(root);
+       return -1;
+    }
+    free(s);
+    set=plover_razor_set_create_from_yum(base);
+    if (!set)
+    {
+       razor_root_close(root);
+       return -1;
+    }
+    upstream=plover_relocate_packages(set,base,relocations);
+    razor_set_destroy(set);
+    trans=razor_transaction_create(system,upstream);
+    for(i=0;pkgs[i];i++)
+       if (plover_mark_package_for_update(trans,upstream,pkgs[i]))
+       {
+           fprintf(stderr,"%s: Package not found\n",pkgs[i]);
+           razor_root_close(root);
+           return -1;
+       }
+    razor_transaction_resolve(trans);
+    if (razor_transaction_describe(trans)>0)
+    {
+       razor_root_close(root);
+       return -1;
+    }
+    next=razor_transaction_commit(trans);
+    plover_run_transaction(trans,base,install_root,system,next,relocations);
+    razor_root_update(root,next);
+    razor_transaction_destroy(trans);
+    razor_set_destroy(next);
+    razor_set_destroy(upstream);
+    if (prefix)
+       razor_relocations_destroy(relocations);
+    return razor_root_commit(root);
+}
+
+static int plover_mark_packages_for_removal(struct razor_transaction *trans,
+  struct razor_set *set,const char *pkg)
+{
+    struct razor_package_iterator *pi;
+    struct razor_package *package;
+    const char *name;
+    int retval=pkg?-1:0;
+    pi=razor_package_iterator_create(set);
+    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
+      RAZOR_DETAIL_LAST))
+    {
+       if (!pkg || !strcmp(name,pkg))
+       {
+           razor_transaction_remove_package(trans,package);
+           retval=0;
+       }
+    }
+    razor_package_iterator_destroy(pi);
+    return retval;
+}
+
+int plover_remove(char **pkgs)
+{
+    int i;
+    char *install_root;
+    struct razor_root *root;
+    struct razor_set *system,*set,*upstream,*next;
+    struct razor_transaction *trans;
+    install_root=getenv("RAZOR_ROOT");
+    if (!install_root)
+       install_root="";
+    set=razor_root_open_read_only(install_root);
+    if (!set)
+       return 0;
+    razor_set_destroy(set);
+    root=razor_root_open(install_root);
+    if (!root)
+       return -1;
+    system=razor_root_get_system_set(root);
+    if (!system)
+    {
+       razor_root_close(root);
+       return -1;
+    }
+    upstream=razor_set_create_without_root();
+    trans=razor_transaction_create(system,upstream);
+    if (pkgs)
+       for(i=0;pkgs[i];i++)
+       {
+           if (plover_mark_packages_for_removal(trans,system,pkgs[i]))
+           {
+               fprintf(stderr,"%s: Package not found\n",pkgs[i]);
+               razor_transaction_destroy(trans);
+               razor_set_destroy(upstream);
+               razor_set_destroy(system);
+               razor_root_close(root);
+               return -1;
+           }
+       }
+    else
+       plover_mark_packages_for_removal(trans,system,NULL);
+    razor_transaction_resolve(trans);
+    if (razor_transaction_describe(trans)>0)
+    {
+       razor_transaction_destroy(trans);
+       razor_set_destroy(upstream);
+       razor_set_destroy(system);
+       razor_root_close(root);
+       return -1;
+    }
+    next=razor_transaction_commit(trans);
+    plover_run_transaction(trans,NULL,install_root,system,next,NULL);
+    razor_root_update(root,next);
+    razor_transaction_destroy(trans);
+    razor_set_destroy(next);
+    razor_set_destroy(upstream);
+    return razor_root_commit(root);
+}
diff --git a/plover/util.c b/plover/util.c
new file mode 100644 (file)
index 0000000..df4d3f9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "config.h"
+#include "plover.h"
+
+char *plover_strconcat(const char *string,...)
+{
+    va_list ap,aq;
+    size_t n;
+    char *result=NULL,*t;
+    const char *s;
+    if (string)
+    {
+       va_start(ap,string);
+       va_copy(aq,ap);
+       n=strlen(string);
+       while((s=va_arg(aq,const char *)))
+           n+=strlen(s);
+       va_end(aq);
+       result=malloc(n+1);
+       if (result)
+       {
+           strcpy(result,string);
+           t=result+strlen(result);
+           while((s=va_arg(ap,const char *)))
+           {
+               strcpy(t,s);
+               t+=strlen(t);
+           }
+       }
+       va_end(ap);
+    }
+    return result;
+}
diff --git a/setup/Makefile.am b/setup/Makefile.am
new file mode 100644 (file)
index 0000000..78c729a
--- /dev/null
@@ -0,0 +1,22 @@
+AM_CFLAGS=-g $(SETUP_CFLAGS)
+LDADD=../plover/libplover.la $(SETUP_LIBS)
+INCLUDES=-I$(top_srcdir)
+
+bin_PROGRAMS=setup
+
+setup_SOURCES=setup.c
+setup_LDFLAGS=-all-static
+if HAVE_WINDRES
+setup_SOURCES+=resources.rc
+endif
+
+.png.pnm:
+       pngtopnm $< | pnmquant 256 > $@
+
+resources.$(OBJEXT): resources.rc setup.ico
+       $(WINDRES) resources.rc $@
+
+setup.ico:     icon16.pnm icon22.pnm icon32.pnm
+        ppmtowinicon -output=$@ $^
+
+EXTRA_DIST=icon16.png icon22.png icon32.png
diff --git a/setup/icon16.png b/setup/icon16.png
new file mode 100644 (file)
index 0000000..0ca1590
Binary files /dev/null and b/setup/icon16.png differ
diff --git a/setup/icon22.png b/setup/icon22.png
new file mode 100644 (file)
index 0000000..4b7f82c
Binary files /dev/null and b/setup/icon22.png differ
diff --git a/setup/icon32.png b/setup/icon32.png
new file mode 100644 (file)
index 0000000..361cd51
Binary files /dev/null and b/setup/icon32.png differ
diff --git a/setup/resources.rc.in b/setup/resources.rc.in
new file mode 100644 (file)
index 0000000..51a31cf
--- /dev/null
@@ -0,0 +1,32 @@
+#include <winver.h>
+
+MAINICON ICON "setup.ico"
+
+VS_VERSION_INFO VERSIONINFO
+    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS
+ION@,0
+    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V
+ERSION@,0
+    FILEOS VOS__WINDOWS32
+    FILETYPE VFT_APP
+    {
+       BLOCK "StringFileInfo"
+       {
+           BLOCK "080904B0"
+           {
+               VALUE "CompanyName","The plover development team"
+               VALUE "FileDescription","Plover setup program"
+               VALUE "FileVersion","@PACKAGE_VERSION@"
+               VALUE "InternalName","setup"
+               VALUE "LegalCopyright",
+                 "Copyright (c) 2009 J. Ali Harlow et al"
+               VALUE "OriginalFilename","setup.exe"
+               VALUE "ProductName","plover"
+               VALUE "ProductVersion","@PACKAGE_VERSION@"
+           }
+       }
+       BLOCK "VarFileInfo"
+       {
+           VALUE "Translation",0x809,0x4B0
+       }
+    }
diff --git a/setup/setup.c b/setup/setup.c
new file mode 100644 (file)
index 0000000..9bfbda1
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#ifdef WIN32
+#include <windows.h>
+#include <shlobj.h>
+#endif
+#include <lua.h>
+#include "config.h"
+#include "plover/plover.h"
+#include "whelk/whelk.h"
+
+LUALIB_API int luaopen_posix(lua_State *L);
+
+struct vector {
+    int len,alloc;
+    char **strings;
+};
+
+struct vector *vector_new(void)
+{
+    struct vector *vector;
+    vector=malloc(sizeof(*vector));
+    vector->len=0;
+    vector->alloc=16;
+    vector->strings=calloc(vector->alloc,sizeof(char *));
+    return vector;
+}
+
+void vector_append(struct vector *vector,const char *str)
+{
+    if (++(vector->len)>=vector->alloc)
+    {
+       vector->alloc*=2;
+       vector->strings=realloc(vector->strings,vector->alloc*sizeof(char *));
+    }
+    vector->strings[vector->len-1]=strdup(str);
+    vector->strings[vector->len]=NULL;
+}
+
+int vector_contains(struct vector *vector,const char *str)
+{
+    int i;
+    for(i=0;i<vector->len;i++)
+       if (!strcmp(vector->strings[i],str))
+           return 1;
+    return 0;
+}
+
+void vector_free(struct vector *vector)
+{
+    int i;
+    for(i=0;i<vector->len;i++)
+       free(vector->strings[i]);
+    free(vector->strings);
+    free(vector);
+}
+
+static void *alloc_lua(void *user_data,void *ptr,size_t osize,size_t nsize)
+{
+    if (!nsize)
+    {
+       free(ptr);
+       return NULL;
+    }
+    else
+       return realloc(ptr,nsize);
+}
+
+void setup()
+{
+    char path[PATH_MAX],*s,*t,*prefix;
+    int changed;
+    struct comps *comps;
+    struct comps_group *group;
+    struct comps_requirement *pkg;
+    struct vector *packages=NULL;
+#ifdef WIN32
+    SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES|CSIDL_FLAG_DONT_VERIFY,NULL,0,
+      path);
+    prefix=strdup(path);
+    GetModuleFileName(NULL,path,sizeof(path));
+    s=strrchr(path,'/');
+    if (s)
+    {
+       t=strrchr(s,'\\');
+       if (t)
+           s=t;
+    }
+    else
+       s=strrchr(path,'\\');
+    if (s)
+       *s='\0';
+#else
+    strcpy(path,"/tmp");
+    prefix=NULL;
+#endif
+    s=plover_strconcat(path,"/repodata/comps.xml",NULL);
+    comps=plover_comps_new_from_file(s);
+    if (!comps)
+    {
+       perror(s);
+       exit(1);
+    }
+    free(s);
+#ifdef WIN32
+    s=plover_strconcat(prefix,"\\",comps->vendor?comps->vendor:"Plover",NULL);
+    free(prefix);
+    prefix=s;
+#endif
+    group=plover_comps_lookup_group(comps,"base");
+    if (!group)
+    {
+       fprintf(stderr,"No base group found in comps.xml\n");
+       exit(1);
+    }
+    packages=vector_new();
+    do
+    {
+       changed=0;
+       for(pkg=group->packages;pkg;pkg=pkg->next)
+       {
+           if (vector_contains(packages,pkg->name))
+               continue;
+           if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
+             pkg->type==COMPS_REQUIREMENT_MANDATORY ||
+             pkg->type==COMPS_REQUIREMENT_CONDITIONAL &&
+             vector_contains(packages,pkg->requires))
+           {
+               changed++;
+               vector_append(packages,pkg->name);
+           }
+       }
+    } while(changed);
+    if (!packages->len)
+    {
+       fprintf(stderr,"No packages to install\n");
+       exit(1);
+    }
+    plover_install(path,prefix,packages->strings);
+    vector_free(packages);
+    plover_comps_free(comps);
+#ifdef WIN32
+    free(prefix);
+#endif
+}
+
+int main(int argc,char **argv)
+{
+    razor_set_lua_loader("posix",luaopen_posix);
+    razor_set_lua_loader("whelk",luaopen_whelk);
+    if (argc>1 && !strcmp(argv[1],"-u"))
+       plover_remove(NULL);
+    else
+       setup();
+}