plover-gtk/packageset.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Mar 23 20:29:50 2012 +0000 (2012-03-23)
changeset 23 e29384105b8d
parent 13 b0a35bae4961
permissions -rw-r--r--
Release 0.4.3
     1 /*
     2  * Copyright (C) 2010-2012  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include "config.h"
    20 #include <stdlib.h>
    21 #include <string.h>
    22 #include <fcntl.h>
    23 #include <errno.h>
    24 #include <unistd.h>
    25 #include <glib-object.h>
    26 #include <razor.h>
    27 #include "plover/plover.h"
    28 #include "plover-gtk/error.h"
    29 #include "plover-gtk/packageset.h"
    30 #include "plover-gtk/package.h"
    31 
    32 G_DEFINE_TYPE(PloverPackageSet,plover_package_set,G_TYPE_OBJECT);
    33 
    34 typedef struct _PloverPackageSetPrivate {
    35     struct razor_root *root;
    36     struct razor_set *set;
    37     GSList *packages;
    38     int no_details;
    39 } PloverPackageSetPrivate;
    40 
    41 #define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
    42 				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
    43 				  PLOVER_TYPE_PACKAGE_SET,\
    44 				  PloverPackageSetPrivate)
    45 
    46 enum {
    47     CHANGED=0,
    48     N_SIGNALS
    49 };
    50 
    51 static guint signals[N_SIGNALS];
    52 
    53 static void plover_package_set_finalize(GObject *obj)
    54 {
    55     PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
    56     if (priv->root)
    57 	razor_root_close(priv->root);
    58     if (G_OBJECT_CLASS(plover_package_set_parent_class)->finalize)
    59 	G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj);
    60 }
    61 
    62 static void plover_package_set_dispose(GObject *obj)
    63 {
    64     PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
    65     if (priv->set)
    66     {
    67 	razor_set_unref(priv->set);
    68 	priv->set=NULL;
    69     }
    70     if (G_OBJECT_CLASS(plover_package_set_parent_class)->dispose)
    71 	G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj);
    72 }
    73 
    74 static void plover_package_set_class_init(PloverPackageSetClass *klass)
    75 {
    76     GObjectClass *oclass=G_OBJECT_CLASS(klass);
    77     oclass->finalize=plover_package_set_finalize;
    78     oclass->dispose=plover_package_set_dispose;
    79     g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate));
    80     signals[CHANGED]=g_signal_newv("changed",
    81       G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
    82       g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
    83 }
    84 
    85 static void plover_package_set_init(PloverPackageSet *set)
    86 {
    87     PloverPackageSetPrivate *priv;
    88     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
    89     priv->no_details=-1;
    90 }
    91 
    92 PloverPackageSet *plover_package_set_new(void)
    93 {
    94     return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL);
    95 }
    96 
    97 PloverPackageSet *plover_package_set_new_from_installed(const char *root,
    98   GError **err)
    99 {
   100     PloverPackageSet *set;
   101     PloverPackageSetPrivate *priv;
   102     struct razor_error *error=NULL;
   103     set=plover_package_set_new();
   104     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   105     priv->root=razor_root_open(root,&error);
   106     if (!priv->root)
   107     {
   108 	g_set_error_literal(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   109 	  razor_error_get_msg(error));
   110 	razor_error_free(error);
   111 	g_object_unref(set);
   112 	return NULL;
   113     }
   114     priv->set=razor_set_ref(razor_root_get_system_set(priv->root));
   115     if (!priv->set)
   116     {
   117 	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   118 	  "Failed to get system set from %s",root);
   119 	g_object_unref(set);
   120 	return NULL;
   121     }
   122     return set;
   123 }
   124 
   125 PloverPackageSet *plover_package_set_new_from_repository(const char *base,
   126   struct razor_relocations *relocations,GError **err)
   127 {
   128 #if HAVE_FCHDIR
   129     int fd;
   130 #else
   131     size_t wd_len;
   132     char *wd;
   133 #endif
   134     gchar *s;
   135     struct razor_set *reloc;
   136     struct razor_error *error=NULL;
   137     PloverPackageSet *set;
   138     PloverPackageSetPrivate *priv;
   139     set=plover_package_set_new();
   140     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   141 #if HAVE_FCHDIR
   142     fd=open(".",O_RDONLY);
   143 #else
   144     wd_len=32;
   145     wd=malloc(wd_len);
   146     while (!getcwd(wd,wd_len) && errno==ERANGE)
   147     {
   148 	free(wd);
   149 	wd_len*=2;
   150 	wd=malloc(wd_len);
   151     }
   152 #endif
   153     s=g_build_filename(base,"repodata",NULL);
   154     if (chdir(s)<0)
   155     {
   156 	g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno),
   157 	  "%s: %s",s,g_strerror(errno));
   158 	g_object_unref(set);
   159 #if HAVE_FCHDIR
   160 	close(fd);
   161 #else
   162 	free(wd);
   163 #endif
   164 	return NULL;
   165     }
   166     g_free(s);
   167     priv->set=plover_razor_set_create_from_yum("..");
   168 #if HAVE_FCHDIR
   169     (void)fchdir(fd);
   170     close(fd);
   171 #else
   172     chdir(wd);
   173     free(wd);
   174 #endif
   175     if (priv->set && relocations)
   176     {
   177 	reloc=plover_relocate_packages(priv->set,base,relocations,&error);
   178 	if (!reloc)
   179 	{
   180 	    g_set_error_literal(err,PLOVER_RAZOR_ERROR,
   181 	      PLOVER_RAZOR_ERROR_FAILED,razor_error_get_msg(error));
   182 	    razor_error_free(error);
   183 	    g_object_unref(set);
   184 	    return NULL;
   185 	}
   186 	razor_set_unref(priv->set);
   187 	priv->set=reloc;
   188     }
   189     if (!priv->set)
   190     {
   191 	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   192 	  "Failed to create package set from repository %s",base);
   193 	g_object_unref(set);
   194 	return NULL;
   195     }
   196     return set;
   197 }
   198 
   199 GSList *plover_package_set_get_packages(PloverPackageSet *set)
   200 {
   201     struct razor_package_iterator *iter;
   202     struct razor_package *pkg;
   203     PloverPackageSetPrivate *priv;
   204     PloverPackage *package;
   205     g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
   206     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   207     if (priv->set && !priv->packages)
   208     {
   209 	iter=razor_package_iterator_create(priv->set);
   210 	while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST))
   211 	{
   212 	    package=plover_package_new(priv->set,pkg);
   213 	    priv->packages=g_slist_prepend(priv->packages,package);
   214 	}
   215 	razor_package_iterator_destroy(iter);
   216     }
   217     return priv->packages;
   218 }
   219 
   220 /*
   221  * Some versions of razor have a bug which causes all detail strings
   222  * to be discarded. If such a version of razor is used to install or
   223  * update a package, then all the detail strings for the installed
   224  * set will be lost. This function tests for this condition and can
   225  * be used to present something more useful than blank details.
   226  */
   227 
   228 gboolean plover_package_set_get_no_details(PloverPackageSet *set)
   229 {
   230     PloverPackageSetPrivate *priv;
   231     PloverPackage *package;
   232     GSList *packages,*link;
   233     g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
   234     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   235     if (priv->no_details<0)
   236     {
   237 	packages=plover_package_set_get_packages(set);
   238 	if (packages)
   239 	{
   240 	    priv->no_details=0;
   241 	    for(link=packages;link;link=link->next)
   242 	    {
   243 		package=link->data;
   244 		priv->no_details+=2;
   245 		if (*plover_package_get_summary(package))
   246 		    priv->no_details--;
   247 		if (*plover_package_get_license(package))
   248 		    priv->no_details--;
   249 		if (*plover_package_get_description(package))
   250 		    priv->no_details--;
   251 		if (*plover_package_get_URL(package))
   252 		    priv->no_details--;
   253 	    }
   254 	    if (priv->no_details<0)	/* More than 50% of strings present */
   255 		priv->no_details=0;
   256 	}
   257     }
   258     return priv->no_details>0;
   259 }