plover/packageset.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jun 13 12:18:42 2016 +0100 (2016-06-13)
changeset 38 a29623b68ca2
parent 26 9816b7a56c23
child 42 419a02fa70db
permissions -rw-r--r--
Add a testsuite and fix bugs found with it
ali@24
     1
/*
ali@24
     2
 * Copyright (C) 2010-2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
ali@24
     3
 *
ali@24
     4
 * This program is free software; you can redistribute it and/or modify
ali@24
     5
 * it under the terms of the GNU General Public License as published by
ali@24
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@24
     7
 * (at your option) any later version.
ali@24
     8
 *
ali@24
     9
 * This program is distributed in the hope that it will be useful,
ali@24
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@24
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@24
    12
 * GNU General Public License for more details.
ali@24
    13
 *
ali@24
    14
 * You should have received a copy of the GNU General Public License along
ali@24
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@24
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@24
    17
 */
ali@24
    18
ali@24
    19
#include "config.h"
ali@24
    20
#include <stdlib.h>
ali@24
    21
#include <string.h>
ali@24
    22
#include <fcntl.h>
ali@24
    23
#include <errno.h>
ali@24
    24
#include <unistd.h>
ali@24
    25
#include <glib-object.h>
ali@24
    26
#include <razor.h>
ali@24
    27
#include "plover/plover.h"
ali@24
    28
#include "plover/package.h"
ali@24
    29
#include "plover/packageset.h"
ali@24
    30
ali@24
    31
G_DEFINE_TYPE(PloverPackageSet,plover_package_set,G_TYPE_OBJECT);
ali@24
    32
ali@24
    33
typedef struct _PloverPackageSetPrivate {
ali@24
    34
    gchar *install_root;
ali@24
    35
    struct razor_root *root;
ali@24
    36
    struct razor_set *set;
ali@24
    37
    GSList *packages;
ali@24
    38
    int no_details;
ali@24
    39
    gchar *guessed_prefix;
ali@24
    40
} PloverPackageSetPrivate;
ali@24
    41
ali@24
    42
#define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
ali@24
    43
				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
ali@24
    44
				  PLOVER_TYPE_PACKAGE_SET,\
ali@24
    45
				  PloverPackageSetPrivate)
ali@24
    46
ali@24
    47
enum {
ali@24
    48
    CHANGED=0,
ali@24
    49
    N_SIGNALS
ali@24
    50
};
ali@24
    51
ali@24
    52
static guint signals[N_SIGNALS];
ali@24
    53
ali@24
    54
static void plover_package_set_finalize(GObject *obj)
ali@24
    55
{
ali@24
    56
    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
ali@24
    57
    g_free(priv->guessed_prefix);
ali@38
    58
    g_free(priv->install_root);
ali@24
    59
    G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj);
ali@24
    60
}
ali@24
    61
ali@24
    62
static void plover_package_set_dispose(GObject *obj)
ali@24
    63
{
ali@24
    64
    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
ali@38
    65
    if (priv->packages)
ali@38
    66
    {
ali@38
    67
	g_slist_foreach(priv->packages,(GFunc)g_object_unref,NULL);
ali@38
    68
	g_slist_free(priv->packages);
ali@38
    69
	priv->packages=NULL;
ali@38
    70
    }
ali@24
    71
    if (priv->set)
ali@24
    72
    {
ali@24
    73
	razor_set_unref(priv->set);
ali@24
    74
	priv->set=NULL;
ali@24
    75
    }
ali@24
    76
    if (priv->root)
ali@24
    77
    {
ali@24
    78
	g_free(priv->install_root);
ali@24
    79
	priv->install_root=NULL;
ali@24
    80
	razor_root_close(priv->root);
ali@24
    81
	priv->root=NULL;
ali@24
    82
    }
ali@24
    83
    G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj);
ali@24
    84
}
ali@24
    85
ali@24
    86
static void plover_package_set_class_init(PloverPackageSetClass *klass)
ali@24
    87
{
ali@24
    88
    GObjectClass *oclass=G_OBJECT_CLASS(klass);
ali@24
    89
    oclass->finalize=plover_package_set_finalize;
ali@24
    90
    oclass->dispose=plover_package_set_dispose;
ali@24
    91
    g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate));
ali@24
    92
    signals[CHANGED]=g_signal_newv("changed",
ali@24
    93
      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
ali@24
    94
      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
ali@24
    95
}
ali@24
    96
ali@24
    97
static void plover_package_set_init(PloverPackageSet *set)
ali@24
    98
{
ali@24
    99
    PloverPackageSetPrivate *priv;
ali@24
   100
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   101
    priv->no_details=-1;
ali@24
   102
}
ali@24
   103
ali@24
   104
PloverPackageSet *plover_package_set_new(void)
ali@24
   105
{
ali@24
   106
    return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL);
ali@24
   107
}
ali@24
   108
ali@24
   109
void plover_package_set_close(PloverPackageSet *set)
ali@24
   110
{
ali@24
   111
    PloverPackageSetPrivate *priv;
ali@24
   112
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
ali@24
   113
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   114
    if (priv->root)
ali@24
   115
    {
ali@24
   116
	razor_root_close(priv->root);
ali@24
   117
	priv->root=NULL;
ali@24
   118
    }
ali@24
   119
}
ali@24
   120
ali@24
   121
gboolean plover_package_set_open(PloverPackageSet *set,const char *install_root,
ali@24
   122
  gboolean exclusive,GError **err)
ali@24
   123
{
ali@24
   124
    struct razor_root *root=NULL;
ali@24
   125
    struct razor_set *system=NULL;
ali@24
   126
    PloverPackageSetPrivate *priv;
ali@24
   127
    struct razor_error *error=NULL;
ali@24
   128
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
ali@24
   129
    if (exclusive)
ali@24
   130
    {
ali@24
   131
	root=razor_root_open(install_root,NULL);
ali@24
   132
	if (!root)
ali@24
   133
	{
ali@24
   134
	    if (razor_root_create(install_root,&error))
ali@24
   135
	    {
ali@24
   136
		if (razor_error_get_domain(error)==RAZOR_GENERAL_ERROR &&
ali@24
   137
		  razor_error_get_code(error)==
ali@24
   138
		  RAZOR_GENERAL_ERROR_DATABASE_EXISTS)
ali@24
   139
		{
ali@24
   140
		    razor_error_free(error);
ali@24
   141
		    error=NULL;
ali@24
   142
		    root=razor_root_open(install_root,&error);
ali@24
   143
		}                             
ali@24
   144
	    }
ali@24
   145
	    else
ali@24
   146
		root=razor_root_open(install_root,&error);
ali@24
   147
	    if (!root)                        
ali@24
   148
	    {
ali@24
   149
		plover_propagate_razor_error(err,error);
ali@24
   150
		return FALSE;
ali@24
   151
	    }
ali@24
   152
	}
ali@24
   153
	system=razor_root_get_system_set(root);
ali@24
   154
	if (system)
ali@24
   155
	    razor_set_ref(system);
ali@24
   156
    }
ali@24
   157
    else
ali@24
   158
	system=razor_root_open_read_only(install_root,&error);
ali@24
   159
    if (error)
ali@24
   160
    {
ali@24
   161
	g_set_error_literal(err,PLOVER_RAZOR_ERROR,RAZOR_GENERAL_ERROR_FAILED,
ali@24
   162
	  razor_error_get_msg(error));
ali@24
   163
	razor_error_free(error);
ali@24
   164
	return FALSE;
ali@24
   165
    }
ali@24
   166
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   167
    if (priv->set)
ali@24
   168
    {
ali@24
   169
	razor_set_unref(priv->set);
ali@24
   170
	priv->set=NULL;
ali@24
   171
    }
ali@24
   172
    if (priv->root)
ali@24
   173
    {
ali@24
   174
	razor_root_close(priv->root);
ali@24
   175
	priv->root=NULL;
ali@24
   176
    }
ali@24
   177
    g_free(priv->install_root);
ali@24
   178
    priv->install_root=g_strdup(install_root);
ali@24
   179
    priv->root=root;
ali@24
   180
    priv->set=system;
ali@24
   181
    return TRUE;
ali@24
   182
}
ali@24
   183
ali@24
   184
const char *plover_package_set_get_install_root(PloverPackageSet *set)
ali@24
   185
{
ali@24
   186
    PloverPackageSetPrivate *priv;
ali@24
   187
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   188
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   189
    return priv->install_root;
ali@24
   190
}
ali@24
   191
ali@24
   192
gboolean plover_package_set_get_exclusive(PloverPackageSet *set)
ali@24
   193
{
ali@24
   194
    PloverPackageSetPrivate *priv;
ali@24
   195
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
ali@24
   196
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   197
    return !!priv->root;
ali@24
   198
}
ali@24
   199
ali@24
   200
gboolean plover_package_set_update(PloverPackageSet *set,struct razor_set *next,
ali@24
   201
  struct razor_atomic *atomic)
ali@24
   202
{
ali@24
   203
    gboolean retval;
ali@24
   204
    PloverPackageSetPrivate *priv;
ali@24
   205
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
ali@24
   206
    g_return_val_if_fail(plover_package_set_get_exclusive(set) != FALSE,FALSE);
ali@24
   207
    g_return_val_if_fail(next != NULL,FALSE);
ali@24
   208
    g_return_val_if_fail(atomic != NULL,FALSE);
ali@24
   209
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   210
    retval=!razor_root_update(priv->root,next,atomic);
ali@24
   211
    if (retval)
ali@24
   212
    {
ali@24
   213
	razor_set_unref(priv->set);
ali@24
   214
	priv->set=razor_root_get_system_set(priv->root);
ali@24
   215
	if (priv->set)
ali@24
   216
	    razor_set_ref(priv->set);
ali@24
   217
    }
ali@24
   218
    return retval;
ali@24
   219
}
ali@24
   220
ali@24
   221
PloverPackageSet *plover_package_set_new_from_installed(const char *root,
ali@24
   222
  GError **err)
ali@24
   223
{
ali@24
   224
    PloverPackageSet *set;
ali@24
   225
    set=plover_package_set_new();
ali@24
   226
    if (!plover_package_set_open(set,root,FALSE,err))
ali@24
   227
    {
ali@24
   228
	g_object_unref(set);
ali@24
   229
	return NULL;
ali@24
   230
    }
ali@24
   231
    return set;
ali@24
   232
}
ali@24
   233
ali@24
   234
PloverPackageSet *plover_package_set_new_from_razor(struct razor_set *razor)
ali@24
   235
{
ali@24
   236
    PloverPackageSet *set;
ali@24
   237
    PloverPackageSetPrivate *priv;
ali@24
   238
    g_return_val_if_fail(razor != NULL,NULL);
ali@24
   239
    set=plover_package_set_new();
ali@24
   240
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   241
    priv->set=razor;
ali@24
   242
    razor_set_ref(priv->set);
ali@24
   243
    return set;
ali@24
   244
}
ali@24
   245
ali@24
   246
static gboolean
ali@24
   247
  plover_package_set_import_package(PloverRepository *repository,
ali@24
   248
  struct razor_relocations *relocations,struct razor_importer *importer,
ali@24
   249
  PloverPackage *package,GError **error)
ali@24
   250
{
ali@26
   251
    int i;
ali@24
   252
    struct razor_property_iterator *prop_iter;
ali@24
   253
    struct razor_file_iterator *file_iter;
ali@24
   254
    struct razor_rpm *rpm;
ali@24
   255
    struct razor_property *prop;
ali@24
   256
    const char *name,*version,*arch,*summary,*desc,*url,*license;
ali@26
   257
    const char *install_prefix;
ali@26
   258
    const char *const *prefixes;
ali@24
   259
    uint32_t flags;
ali@24
   260
    rpm=plover_repository_open_rpm(repository,package,error);
ali@24
   261
    if (!rpm)
ali@24
   262
	return FALSE;
ali@24
   263
    razor_relocations_set_rpm(relocations,rpm);
ali@24
   264
    name=plover_package_get_name(package);
ali@24
   265
    version=plover_package_get_version(package);
ali@24
   266
    arch=plover_package_get_arch(package);
ali@24
   267
    razor_importer_begin_package(importer,name,version,arch);
ali@24
   268
    summary=plover_package_get_summary(package);
ali@24
   269
    desc=plover_package_get_description(package);
ali@24
   270
    url=plover_package_get_URL(package);
ali@24
   271
    license=plover_package_get_license(package);
ali@24
   272
    razor_importer_add_details(importer,summary,desc,url,license);
ali@26
   273
    razor_rpm_get_details(rpm,RAZOR_DETAIL_PREFIXES,&prefixes,
ali@26
   274
      RAZOR_DETAIL_LAST);
ali@26
   275
    for(i=0;prefixes && prefixes[i];i++)
ali@26
   276
    {
ali@26
   277
	install_prefix=razor_relocations_apply(relocations,prefixes[i]);
ali@26
   278
	razor_importer_add_install_prefix(importer,install_prefix);
ali@26
   279
    }
ali@26
   280
    razor_rpm_close(rpm);
ali@24
   281
    prop_iter=plover_package_property_iterator_create(package);
ali@24
   282
    while (razor_property_iterator_next(prop_iter,&prop,&name,&flags,&version))
ali@24
   283
	razor_importer_add_property(importer,name,flags,version);
ali@24
   284
    razor_property_iterator_destroy(prop_iter);
ali@24
   285
    file_iter=plover_package_file_iterator_create(package,FALSE);
ali@24
   286
    while (razor_file_iterator_next(file_iter,&name))
ali@24
   287
    {
ali@24
   288
	name=razor_relocations_apply(relocations,name);
ali@24
   289
	razor_importer_add_file(importer,name);
ali@24
   290
    }
ali@24
   291
    razor_file_iterator_destroy(file_iter);
ali@24
   292
    razor_importer_finish_package(importer);
ali@24
   293
    return TRUE;
ali@24
   294
}
ali@24
   295
ali@24
   296
PloverPackageSet *
ali@24
   297
  plover_package_set_new_from_repository(PloverRepository *repository,
ali@24
   298
  struct razor_relocations *relocations,GError **error)
ali@24
   299
{
ali@24
   300
    struct razor_importer *importer;
ali@24
   301
    uint32_t header_version;
ali@24
   302
    GSList *packages,*lnk;
ali@24
   303
    PloverPackageSet *unrelocated,*set;
ali@24
   304
    PloverPackageSetPrivate *priv;
ali@24
   305
    PloverPackage *package;
ali@24
   306
    g_return_val_if_fail(PLOVER_IS_REPOSITORY(repository),NULL);
ali@24
   307
    unrelocated=plover_repository_get_package_set(repository);
ali@24
   308
    set=plover_package_set_new();
ali@24
   309
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   310
    if (relocations)
ali@24
   311
    {
ali@24
   312
	importer=razor_importer_create();
ali@24
   313
	packages=plover_package_set_get_packages(unrelocated);
ali@24
   314
	for(lnk=packages;lnk;lnk=lnk->next)
ali@24
   315
	{
ali@24
   316
	    package=lnk->data;
ali@24
   317
	    if (!plover_package_set_import_package(repository,relocations,
ali@24
   318
	      importer,package,error))
ali@24
   319
	    {
ali@24
   320
		razor_importer_destroy(importer);
ali@24
   321
		g_object_unref(set);
ali@24
   322
		return NULL;
ali@24
   323
	    }
ali@24
   324
	}
ali@24
   325
	priv->set=razor_importer_finish(importer);
ali@24
   326
	if (!priv->set)
ali@24
   327
	{
ali@24
   328
	    g_object_unref(set);
ali@24
   329
	    return NULL;
ali@24
   330
	}
ali@24
   331
	header_version=plover_package_set_get_header_version(unrelocated);
ali@24
   332
	if (header_version)
ali@24
   333
	    plover_package_set_set_header_version(set,header_version);
ali@24
   334
    }
ali@24
   335
    else
ali@24
   336
    {
ali@24
   337
	priv->set=plover_package_set_get_razor(unrelocated);
ali@24
   338
	razor_set_ref(priv->set);
ali@24
   339
    }
ali@24
   340
    return set;
ali@24
   341
}
ali@24
   342
ali@24
   343
PloverPackageSet *plover_package_set_new_from_yum(const char *base,
ali@24
   344
  struct razor_relocations *relocations,GError **error)
ali@24
   345
{
ali@24
   346
    PloverPackageSet *set;
ali@24
   347
    PloverRepository *repository;
ali@24
   348
    repository=plover_repository_new_from_yum(base,error);
ali@24
   349
    if (!repository)
ali@24
   350
	return NULL;
ali@24
   351
    set=plover_package_set_new_from_repository(repository,relocations,error);
ali@24
   352
    g_object_unref(repository);
ali@24
   353
    return set;
ali@24
   354
}
ali@24
   355
ali@24
   356
PloverPackageSet *plover_package_set_new_from_rpms(const char **filenames,
ali@24
   357
  GError **error)
ali@24
   358
{
ali@24
   359
    int i;
ali@24
   360
    PloverPackageSet *set;
ali@24
   361
    PloverPackageSetPrivate *priv;
ali@24
   362
    struct razor_importer *importer;
ali@24
   363
    struct razor_rpm *rpm;
ali@24
   364
    struct razor_error *tmp_error=NULL;
ali@24
   365
    importer=razor_importer_create();
ali@24
   366
    for(i=0;filenames[i];i++)
ali@24
   367
    {
ali@24
   368
	rpm=razor_rpm_open(filenames[i],&tmp_error);
ali@24
   369
	if (!rpm)
ali@24
   370
	{
ali@24
   371
	    razor_importer_destroy(importer);
ali@24
   372
	    plover_propagate_razor_error(error,tmp_error);
ali@24
   373
	    return NULL;
ali@24
   374
	}
ali@24
   375
	if (razor_importer_add_rpm(importer,rpm))
ali@24
   376
	{
ali@24
   377
	    g_set_error(error,PLOVER_RAZOR_ERROR,RAZOR_GENERAL_ERROR_FAILED,
ali@24
   378
	      "%s: failed to import",filenames[i]);
ali@24
   379
	    razor_importer_destroy(importer);
ali@24
   380
	    return NULL;
ali@24
   381
	}
ali@24
   382
	razor_rpm_close(rpm);
ali@24
   383
    }
ali@24
   384
    set=plover_package_set_new();
ali@24
   385
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   386
    priv->set=razor_importer_finish(importer);
ali@24
   387
    return set;
ali@24
   388
}
ali@24
   389
ali@24
   390
uint32_t plover_package_set_get_header_version(PloverPackageSet *set)
ali@24
   391
{
ali@24
   392
    PloverPackageSetPrivate *priv;
ali@24
   393
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),0);
ali@24
   394
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   395
    if (priv->set)
ali@24
   396
	return razor_set_get_header_version(priv->set);
ali@24
   397
    else
ali@24
   398
	return 0;
ali@24
   399
}
ali@24
   400
ali@24
   401
gboolean plover_package_set_set_header_version(PloverPackageSet *set,
ali@24
   402
  uint32_t header_version)
ali@24
   403
{
ali@24
   404
    PloverPackageSetPrivate *priv;
ali@24
   405
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
ali@24
   406
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   407
    if (priv->set)
ali@24
   408
	return !razor_set_set_header_version(priv->set,header_version);
ali@24
   409
    else
ali@24
   410
	return FALSE;
ali@24
   411
}
ali@24
   412
ali@24
   413
struct razor_set *plover_package_set_get_razor(PloverPackageSet *set)
ali@24
   414
{
ali@24
   415
    PloverPackageSetPrivate *priv;
ali@24
   416
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   417
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   418
    return priv->set;
ali@24
   419
}
ali@24
   420
ali@24
   421
GSList *plover_package_set_get_packages(PloverPackageSet *set)
ali@24
   422
{
ali@24
   423
    struct razor_package_iterator *iter;
ali@24
   424
    struct razor_package *pkg;
ali@24
   425
    PloverPackageSetPrivate *priv;
ali@24
   426
    PloverPackage *package;
ali@24
   427
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   428
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   429
    if (priv->set && !priv->packages)
ali@24
   430
    {
ali@24
   431
	iter=razor_package_iterator_create(priv->set);
ali@24
   432
	while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST))
ali@24
   433
	{
ali@24
   434
	    package=plover_package_new(priv->set,pkg);
ali@24
   435
	    priv->packages=g_slist_prepend(priv->packages,package);
ali@24
   436
	}
ali@24
   437
	razor_package_iterator_destroy(iter);
ali@24
   438
	priv->packages=g_slist_reverse(priv->packages);
ali@24
   439
    }
ali@24
   440
    return priv->packages;
ali@24
   441
}
ali@24
   442
ali@24
   443
PloverPackage *plover_package_set_lookup(PloverPackageSet *set,
ali@24
   444
  struct razor_package *razor_package)
ali@24
   445
{
ali@24
   446
    GSList *packages,*lnk;
ali@24
   447
    PloverPackage *package;
ali@24
   448
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   449
    packages=plover_package_set_get_packages(set);
ali@24
   450
    for(lnk=packages;lnk;lnk=lnk->next)
ali@24
   451
    {
ali@24
   452
	package=lnk->data;
ali@24
   453
	if (plover_package_get_razor_package(package)==razor_package)
ali@24
   454
	    return package;
ali@24
   455
    }
ali@24
   456
    return NULL;
ali@24
   457
}
ali@24
   458
ali@24
   459
PloverPackage *plover_package_set_find_custom(PloverPackageSet *set,
ali@24
   460
  gconstpointer data,GCompareFunc func)
ali@24
   461
{
ali@24
   462
    GSList *packages,*lnk;
ali@24
   463
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   464
    packages=plover_package_set_get_packages(set);
ali@24
   465
    lnk=g_slist_find_custom(packages,data,func);
ali@24
   466
    return lnk?lnk->data:NULL;
ali@24
   467
}
ali@24
   468
ali@24
   469
static gint plover_package_set_compare(gconstpointer a,gconstpointer b)
ali@24
   470
{
ali@24
   471
    PloverPackage *pa=(void *)a,*pb=(void *)b;
ali@24
   472
    const char *sa,*sb;
ali@24
   473
    sa=plover_package_get_name(pa);
ali@24
   474
    sb=plover_package_get_name(pb);
ali@24
   475
    if (g_strcmp0(sa,sb))
ali@24
   476
	return 1;
ali@24
   477
    sa=plover_package_get_arch(pa);
ali@24
   478
    sb=plover_package_get_arch(pb);
ali@24
   479
    if (g_strcmp0(sa,sb))
ali@24
   480
	return 1;
ali@24
   481
    sa=plover_package_get_version(pa);
ali@24
   482
    sb=plover_package_get_version(pb);
ali@24
   483
    return !!g_strcmp0(sa,sb);
ali@24
   484
}
ali@24
   485
ali@24
   486
PloverPackage *plover_package_set_find_matching(PloverPackageSet *set,
ali@24
   487
  PloverPackage *template)
ali@24
   488
{
ali@24
   489
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   490
    return plover_package_set_find_custom(set,template,
ali@24
   491
      plover_package_set_compare);
ali@24
   492
}
ali@24
   493
ali@24
   494
/*
ali@24
   495
 * Some versions of razor have a bug which causes all detail strings
ali@24
   496
 * to be discarded. If such a version of razor is used to install or
ali@24
   497
 * update a package, then all the detail strings for the installed
ali@24
   498
 * set will be lost. This function tests for this condition and can
ali@24
   499
 * be used to present something more useful than blank details.
ali@24
   500
 */
ali@24
   501
ali@24
   502
gboolean plover_package_set_get_no_details(PloverPackageSet *set)
ali@24
   503
{
ali@24
   504
    PloverPackageSetPrivate *priv;
ali@24
   505
    PloverPackage *package;
ali@24
   506
    GSList *packages,*link;
ali@24
   507
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
ali@24
   508
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   509
    if (priv->no_details<0)
ali@24
   510
    {
ali@24
   511
	packages=plover_package_set_get_packages(set);
ali@24
   512
	if (packages)
ali@24
   513
	{
ali@24
   514
	    priv->no_details=0;
ali@24
   515
	    for(link=packages;link;link=link->next)
ali@24
   516
	    {
ali@24
   517
		package=link->data;
ali@24
   518
		priv->no_details+=2;
ali@24
   519
		if (*plover_package_get_summary(package))
ali@24
   520
		    priv->no_details--;
ali@24
   521
		if (*plover_package_get_license(package))
ali@24
   522
		    priv->no_details--;
ali@24
   523
		if (*plover_package_get_description(package))
ali@24
   524
		    priv->no_details--;
ali@24
   525
		if (*plover_package_get_URL(package))
ali@24
   526
		    priv->no_details--;
ali@24
   527
	    }
ali@24
   528
	    if (priv->no_details<0)	/* More than 50% of strings present */
ali@24
   529
		priv->no_details=0;
ali@24
   530
	}
ali@24
   531
    }
ali@24
   532
    return priv->no_details>0;
ali@24
   533
}
ali@24
   534
ali@24
   535
struct plover_package_set_prefix {
ali@24
   536
    gchar *path;
ali@24
   537
    guint count;
ali@24
   538
};
ali@24
   539
ali@24
   540
static GArray *plover_package_set_popchart_new(void)
ali@24
   541
{
ali@24
   542
    GArray *prefixes;
ali@24
   543
    prefixes=g_array_new(FALSE,FALSE,sizeof(struct plover_package_set_prefix));
ali@24
   544
    return prefixes;
ali@24
   545
}
ali@24
   546
ali@24
   547
static void plover_package_set_popchart_free(GArray *popchart)
ali@24
   548
{
ali@24
   549
    int i;
ali@24
   550
    struct plover_package_set_prefix *prefix;
ali@24
   551
    for(i=0;i<popchart->len;i++)
ali@24
   552
    {
ali@24
   553
	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
ali@24
   554
	g_free(prefix->path);
ali@24
   555
    }
ali@24
   556
    g_array_free(popchart,TRUE);
ali@24
   557
}
ali@24
   558
ali@24
   559
static void plover_package_set_popchart_add(GArray *popchart,const char *path)
ali@24
   560
{
ali@24
   561
    int i;
ali@24
   562
    struct plover_package_set_prefix *prefix;
ali@24
   563
    for(i=popchart->len-1;i>=0;i--)
ali@24
   564
    {
ali@24
   565
	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
ali@24
   566
	if (!strcmp(prefix->path,path))
ali@24
   567
	{
ali@24
   568
	    prefix->count++;
ali@24
   569
	    return;
ali@24
   570
	}
ali@24
   571
    }
ali@24
   572
    g_array_set_size(popchart,popchart->len+1);
ali@24
   573
    prefix=&g_array_index(popchart,struct plover_package_set_prefix,
ali@24
   574
      popchart->len-1);
ali@24
   575
    prefix->path=g_strdup(path);
ali@24
   576
    prefix->count=1;
ali@24
   577
}
ali@24
   578
ali@24
   579
static const char *plover_package_set_popchart_get_popular(GArray *popchart)
ali@24
   580
{
ali@24
   581
    int i;
ali@24
   582
    struct plover_package_set_prefix *prefix,*popular;
ali@24
   583
    if (!popchart->len)
ali@24
   584
	return NULL;
ali@24
   585
    popular=&g_array_index(popchart,struct plover_package_set_prefix,0);
ali@24
   586
    for(i=1;i<popchart->len;i++)
ali@24
   587
    {
ali@24
   588
	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
ali@24
   589
	if (prefix->count>popular->count)
ali@24
   590
	    popular=prefix;
ali@24
   591
    }
ali@24
   592
    return popular->path;
ali@24
   593
}
ali@24
   594
ali@24
   595
static void plover_package_set_popchart_add_prefixes(PloverPackageSet *set,
ali@24
   596
  GArray *popchart)
ali@24
   597
{
ali@24
   598
    int i;
ali@24
   599
    PloverPackage *package;
ali@24
   600
    GSList *packages,*lnk;
ali@24
   601
    const char *const *prefixes;
ali@24
   602
    packages=plover_package_set_get_packages(set);
ali@24
   603
    for(lnk=packages;lnk;lnk=lnk->next)
ali@24
   604
    {
ali@24
   605
	package=lnk->data;
ali@24
   606
	prefixes=plover_package_get_prefixes(package);
ali@24
   607
	for(i=0;prefixes[i];i++)
ali@24
   608
	    plover_package_set_popchart_add(popchart,prefixes[i]);
ali@24
   609
    }
ali@24
   610
}
ali@24
   611
ali@24
   612
static void plover_package_set_popchart_add_from_files(PloverPackageSet *set,
ali@24
   613
  GArray *popchart)
ali@24
   614
{
ali@24
   615
    int len;
ali@24
   616
    const char *name,*s;
ali@24
   617
    gchar *default_prefix,*path;
ali@24
   618
    struct razor_file_iterator *fi;
ali@24
   619
    GSList *packages,*lnk;
ali@24
   620
    PloverPackage *package;
ali@24
   621
    default_prefix=plover_default_prefix_for_vendor("");
ali@24
   622
    if (!default_prefix)
ali@24
   623
	return;
ali@24
   624
    len=strlen(default_prefix);
ali@24
   625
    packages=plover_package_set_get_packages(set);
ali@24
   626
    for(lnk=packages;lnk;lnk=lnk->next)
ali@24
   627
    {
ali@24
   628
	package=lnk->data;
ali@24
   629
	fi=plover_package_file_iterator_create(package,FALSE);
ali@24
   630
	while (razor_file_iterator_next(fi,&name))
ali@24
   631
	{
ali@24
   632
	    if (g_str_has_prefix(name,default_prefix))
ali@24
   633
	    {
ali@24
   634
		for(s=name+len;*s;s++)
ali@24
   635
		    if (G_IS_DIR_SEPARATOR(*s))
ali@24
   636
			break;
ali@24
   637
		path=g_strndup(name,s-name);
ali@24
   638
		plover_package_set_popchart_add(popchart,path);
ali@24
   639
		g_free(path);
ali@24
   640
	    }
ali@24
   641
	}
ali@24
   642
	razor_file_iterator_destroy(fi);
ali@24
   643
    }
ali@24
   644
    g_free(default_prefix);
ali@24
   645
}
ali@24
   646
ali@24
   647
const char *plover_package_set_guess_prefix(PloverPackageSet *set,
ali@24
   648
  GError **error)
ali@24
   649
{
ali@24
   650
    GArray *popchart;
ali@24
   651
    const char *prefix;
ali@24
   652
    PloverPackageSetPrivate *priv;
ali@24
   653
    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
ali@24
   654
    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
ali@24
   655
    if (!priv->guessed_prefix)
ali@24
   656
    {
ali@24
   657
	popchart=plover_package_set_popchart_new();
ali@24
   658
	plover_package_set_popchart_add_prefixes(set,popchart);
ali@24
   659
	prefix=plover_package_set_popchart_get_popular(popchart);
ali@24
   660
	if (prefix)
ali@24
   661
	    priv->guessed_prefix=g_strdup(prefix);
ali@24
   662
	else
ali@24
   663
	{
ali@24
   664
	    plover_package_set_popchart_add_from_files(set,popchart);
ali@24
   665
	    prefix=plover_package_set_popchart_get_popular(popchart);
ali@24
   666
	    if (prefix)
ali@24
   667
		priv->guessed_prefix=g_strdup(prefix);
ali@24
   668
	}
ali@24
   669
	plover_package_set_popchart_free(popchart);
ali@24
   670
    }
ali@24
   671
    if (!priv->guessed_prefix)
ali@24
   672
	priv->guessed_prefix=
ali@24
   673
	  plover_default_prefix_for_vendor("Acme Corporation");
ali@24
   674
    return priv->guessed_prefix;
ali@24
   675
}