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