plover-gtk/packageset.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jan 30 13:35:28 2012 +0000 (2012-01-30)
changeset 18 cb43820f94ce
parent 10 8b50be3e2998
child 19 5cafc65a6183
permissions -rw-r--r--
Release 0.4.1
     1 /*
     2  * Copyright (C) 2010, 2011  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_atomic *atomic;
    36     struct razor_root *root;
    37     struct razor_set *set;
    38     GSList *packages;
    39     int no_details;
    40 } PloverPackageSetPrivate;
    41 
    42 #define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
    43 				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
    44 				  PLOVER_TYPE_PACKAGE_SET,\
    45 				  PloverPackageSetPrivate)
    46 
    47 enum {
    48     CHANGED=0,
    49     N_SIGNALS
    50 };
    51 
    52 static guint signals[N_SIGNALS];
    53 
    54 static void plover_package_set_finalize(GObject *obj)
    55 {
    56     PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
    57     if (priv->root)
    58 	razor_root_close(priv->root);
    59     if (priv->atomic)
    60 	razor_atomic_destroy(priv->atomic);
    61     if (G_OBJECT_CLASS(plover_package_set_parent_class)->finalize)
    62 	G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj);
    63 }
    64 
    65 static void plover_package_set_dispose(GObject *obj)
    66 {
    67     PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
    68     if (priv->set)
    69     {
    70 	razor_set_unref(priv->set);
    71 	priv->set=NULL;
    72     }
    73     if (G_OBJECT_CLASS(plover_package_set_parent_class)->dispose)
    74 	G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj);
    75 }
    76 
    77 static void plover_package_set_class_init(PloverPackageSetClass *klass)
    78 {
    79     GObjectClass *oclass=G_OBJECT_CLASS(klass);
    80     oclass->finalize=plover_package_set_finalize;
    81     oclass->dispose=plover_package_set_dispose;
    82     g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate));
    83     signals[CHANGED]=g_signal_newv("changed",
    84       G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
    85       g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
    86 }
    87 
    88 static void plover_package_set_init(PloverPackageSet *set)
    89 {
    90     PloverPackageSetPrivate *priv;
    91     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
    92     priv->no_details=-1;
    93 }
    94 
    95 PloverPackageSet *plover_package_set_new(void)
    96 {
    97     return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL);
    98 }
    99 
   100 PloverPackageSet *plover_package_set_new_from_installed(const char *root,
   101   GError **err)
   102 {
   103     PloverPackageSet *set;
   104     PloverPackageSetPrivate *priv;
   105     set=plover_package_set_new();
   106     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   107     priv->atomic=razor_atomic_open("Read root package set");
   108     priv->root=razor_root_open(root,priv->atomic);
   109     if (!priv->root)
   110     {
   111 	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   112 	  "Failed to open %s as razor root",root);
   113 	g_object_unref(set);
   114 	return NULL;
   115     }
   116     priv->set=razor_set_ref(razor_root_get_system_set(priv->root));
   117     if (!priv->set)
   118     {
   119 	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   120 	  "Failed to get system set from %s",root);
   121 	g_object_unref(set);
   122 	return NULL;
   123     }
   124     return set;
   125 }
   126 
   127 PloverPackageSet *plover_package_set_new_from_repository(const char *base,
   128   struct razor_relocations *relocations,GError **err)
   129 {
   130 #if HAVE_FCHDIR
   131     int fd;
   132 #else
   133     size_t wd_len;
   134     char *wd;
   135 #endif
   136     gchar *s;
   137     struct razor_set *reloc;
   138     struct razor_atomic *atomic;
   139     PloverPackageSet *set;
   140     PloverPackageSetPrivate *priv;
   141     set=plover_package_set_new();
   142     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   143 #if HAVE_FCHDIR
   144     fd=open(".",O_RDONLY);
   145 #else
   146     wd_len=32;
   147     wd=malloc(wd_len);
   148     while (!getcwd(wd,wd_len) && errno==ERANGE)
   149     {
   150 	free(wd);
   151 	wd_len*=2;
   152 	wd=malloc(wd_len);
   153     }
   154 #endif
   155     s=g_build_filename(base,"repodata",NULL);
   156     if (chdir(s)<0)
   157     {
   158 	g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno),
   159 	  "%s: %s",s,g_strerror(errno));
   160 	g_object_unref(set);
   161 #if HAVE_FCHDIR
   162 	close(fd);
   163 #else
   164 	free(wd);
   165 #endif
   166 	return NULL;
   167     }
   168     g_free(s);
   169     priv->set=plover_razor_set_create_from_yum("..");
   170 #if HAVE_FCHDIR
   171     (void)fchdir(fd);
   172     close(fd);
   173 #else
   174     chdir(wd);
   175     free(wd);
   176 #endif
   177     if (priv->set && relocations)
   178     {
   179 	atomic=razor_atomic_open("Relocate packages");
   180 	reloc=plover_relocate_packages(priv->set,atomic,base,relocations);
   181 	if (!reloc)
   182 	    g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   183 	      razor_atomic_get_error_msg(atomic));
   184 	razor_atomic_destroy(atomic);
   185 	if (!reloc)
   186 	{
   187 	    g_object_unref(set);
   188 	    return NULL;
   189 	}
   190 	razor_set_unref(priv->set);
   191 	priv->set=reloc;
   192     }
   193     if (!priv->set)
   194     {
   195 	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
   196 	  "Failed to create package set from repository %s",base);
   197 	g_object_unref(set);
   198 	return NULL;
   199     }
   200     return set;
   201 }
   202 
   203 GSList *plover_package_set_get_packages(PloverPackageSet *set)
   204 {
   205     struct razor_package_iterator *iter;
   206     struct razor_package *pkg;
   207     PloverPackageSetPrivate *priv;
   208     PloverPackage *package;
   209     g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
   210     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   211     if (priv->set && !priv->packages)
   212     {
   213 	iter=razor_package_iterator_create(priv->set);
   214 	while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST))
   215 	{
   216 	    package=plover_package_new(priv->set,pkg);
   217 	    priv->packages=g_slist_prepend(priv->packages,package);
   218 	}
   219 	razor_package_iterator_destroy(iter);
   220     }
   221     return priv->packages;
   222 }
   223 
   224 /*
   225  * Some versions of razor have a bug which causes all detail strings
   226  * to be discarded. If such a version of razor is used to install or
   227  * update a package, then all the detail strings for the installed
   228  * set will be lost. This function tests for this condition and can
   229  * be used to present something more useful than blank details.
   230  */
   231 
   232 gboolean plover_package_set_get_no_details(PloverPackageSet *set)
   233 {
   234     PloverPackageSetPrivate *priv;
   235     PloverPackage *package;
   236     GSList *packages,*link;
   237     g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
   238     priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   239     if (priv->no_details<0)
   240     {
   241 	packages=plover_package_set_get_packages(set);
   242 	if (packages)
   243 	{
   244 	    priv->no_details=0;
   245 	    for(link=packages;link;link=link->next)
   246 	    {
   247 		package=link->data;
   248 		priv->no_details+=2;
   249 		if (*plover_package_get_summary(package))
   250 		    priv->no_details--;
   251 		if (*plover_package_get_license(package))
   252 		    priv->no_details--;
   253 		if (*plover_package_get_description(package))
   254 		    priv->no_details--;
   255 		if (*plover_package_get_URL(package))
   256 		    priv->no_details--;
   257 	    }
   258 	    if (priv->no_details<0)	/* More than 50% of strings present */
   259 		priv->no_details=0;
   260 	}
   261     }
   262     return priv->no_details>0;
   263 }