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