1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2014 Richard Hughes <richard@hughsie.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1+
6 */
7
8 /**
9 * SECTION:asb-package
10 * @short_description: Object representing a package file.
11 * @stability: Unstable
12 *
13 * This object represents one package file.
14 */
15
16 #include "config.h"
17
18 #include <limits.h>
19
20 #include "asb-package.h"
21 #include "asb-plugin.h"
22
23 typedef struct
24 {
25 AsbPackageKind kind;
26 gboolean enabled;
27 gboolean is_open;
28 gchar **filelist;
29 guint filelist_refcount;
30 GPtrArray *deps;
31 guint deps_refcount;
32 gchar *filename;
33 gchar *basename;
34 gchar *name;
35 guint epoch;
36 gchar *version;
37 gchar *release;
38 gchar *arch;
39 gchar *url;
40 gchar *nevr;
41 gchar *nevra;
42 gchar *evr;
43 gchar *license;
44 gchar *vcs;
45 gchar *source_nevra;
46 gchar *source_pkgname;
47 gsize log_written_len;
48 GString *log;
49 GHashTable *configs;
50 GTimer *timer;
51 gdouble last_log;
52 GPtrArray *releases;
53 GHashTable *releases_hash;
54 GMutex mutex_log;
55 } AsbPackagePrivate;
56
G_DEFINE_TYPE_WITH_PRIVATE(AsbPackage,asb_package,G_TYPE_OBJECT)57 G_DEFINE_TYPE_WITH_PRIVATE (AsbPackage, asb_package, G_TYPE_OBJECT)
58
59 #define GET_PRIVATE(o) (asb_package_get_instance_private (o))
60
61 static void
62 asb_package_finalize (GObject *object)
63 {
64 AsbPackage *pkg = ASB_PACKAGE (object);
65 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
66
67 g_mutex_clear (&priv->mutex_log);
68 g_strfreev (priv->filelist);
69 g_ptr_array_unref (priv->deps);
70 g_free (priv->filename);
71 g_free (priv->basename);
72 g_free (priv->name);
73 g_free (priv->version);
74 g_free (priv->release);
75 g_free (priv->arch);
76 g_free (priv->url);
77 g_free (priv->nevr);
78 g_free (priv->nevra);
79 g_free (priv->evr);
80 g_free (priv->license);
81 g_free (priv->vcs);
82 g_free (priv->source_nevra);
83 g_free (priv->source_pkgname);
84 g_string_free (priv->log, TRUE);
85 g_timer_destroy (priv->timer);
86 g_hash_table_unref (priv->configs);
87 g_ptr_array_unref (priv->releases);
88 g_hash_table_unref (priv->releases_hash);
89
90 G_OBJECT_CLASS (asb_package_parent_class)->finalize (object);
91 }
92
93 static void
asb_package_init(AsbPackage * pkg)94 asb_package_init (AsbPackage *pkg)
95 {
96 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
97 priv->enabled = TRUE;
98 priv->log = g_string_new (NULL);
99 priv->timer = g_timer_new ();
100 priv->deps = g_ptr_array_new_with_free_func (g_free);
101 priv->configs = g_hash_table_new_full (g_str_hash, g_str_equal,
102 g_free, g_free);
103 priv->releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
104 priv->releases_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
105 g_free, (GDestroyNotify) g_object_unref);
106 g_mutex_init (&priv->mutex_log);
107 }
108
109 /**
110 * asb_package_get_enabled:
111 * @pkg: A #AsbPackage
112 *
113 * Gets if the package is enabled.
114 *
115 * Returns: enabled status
116 *
117 * Since: 0.1.0
118 **/
119 gboolean
asb_package_get_enabled(AsbPackage * pkg)120 asb_package_get_enabled (AsbPackage *pkg)
121 {
122 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
123 return priv->enabled;
124 }
125
126 /**
127 * asb_package_set_enabled:
128 * @pkg: A #AsbPackage
129 * @enabled: boolean
130 *
131 * Enables or disables the package.
132 *
133 * Since: 0.1.0
134 **/
135 void
asb_package_set_enabled(AsbPackage * pkg,gboolean enabled)136 asb_package_set_enabled (AsbPackage *pkg, gboolean enabled)
137 {
138 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
139 priv->enabled = enabled;
140 }
141
142 /**
143 * asb_package_log_start:
144 * @pkg: A #AsbPackage
145 *
146 * Starts the log timer.
147 *
148 * Since: 0.1.0
149 **/
150 void
asb_package_log_start(AsbPackage * pkg)151 asb_package_log_start (AsbPackage *pkg)
152 {
153 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
154 g_timer_reset (priv->timer);
155 }
156
157 /**
158 * asb_package_log:
159 * @pkg: A #AsbPackage
160 * @log_level: a #AsbPackageLogLevel
161 * @fmt: Format string
162 * @...: varargs
163 *
164 * Logs a message.
165 *
166 * Since: 0.1.0
167 **/
168 void
asb_package_log(AsbPackage * pkg,AsbPackageLogLevel log_level,const gchar * fmt,...)169 asb_package_log (AsbPackage *pkg,
170 AsbPackageLogLevel log_level,
171 const gchar *fmt, ...)
172 {
173 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
174 va_list args;
175 gdouble now;
176 g_autofree gchar *tmp = NULL;
177
178 g_mutex_lock (&priv->mutex_log);
179
180 va_start (args, fmt);
181 tmp = g_strdup_vprintf (fmt, args);
182 va_end (args);
183 if (g_getenv ("ASB_PROFILE") != NULL) {
184 now = g_timer_elapsed (priv->timer, NULL) * 1000;
185 g_string_append_printf (priv->log,
186 "%05.0f\t+%05.0f\t",
187 now, now - priv->last_log);
188 priv->last_log = now;
189 }
190 switch (log_level) {
191 case ASB_PACKAGE_LOG_LEVEL_INFO:
192 g_debug ("INFO: %s", tmp);
193 g_string_append_printf (priv->log, "INFO: %s\n", tmp);
194 break;
195 case ASB_PACKAGE_LOG_LEVEL_DEBUG:
196 g_debug ("DEBUG: %s", tmp);
197 g_string_append_printf (priv->log, "DEBUG: %s\n", tmp);
198 break;
199 case ASB_PACKAGE_LOG_LEVEL_WARNING:
200 g_debug ("WARNING: %s", tmp);
201 g_string_append_printf (priv->log, "WARNING: %s\n", tmp);
202 break;
203 default:
204 g_debug ("%s", tmp);
205 g_string_append_printf (priv->log, "%s\n", tmp);
206 break;
207 }
208 g_mutex_unlock (&priv->mutex_log);
209 }
210
211 /**
212 * asb_package_log_flush:
213 * @pkg: A #AsbPackage
214 * @error: A #GError or %NULL
215 *
216 * Flushes the log queue.
217 *
218 * Returns: %TRUE for success, %FALSE otherwise
219 *
220 * Since: 0.1.0
221 **/
222 gboolean
asb_package_log_flush(AsbPackage * pkg,GError ** error)223 asb_package_log_flush (AsbPackage *pkg, GError **error)
224 {
225 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
226 g_autofree gchar *logfile = NULL;
227 g_autofree gchar *logdir_char = NULL;
228
229 /* needs no update */
230 if (priv->log_written_len == priv->log->len)
231 return TRUE;
232
233 /* don't write if unset */
234 if (asb_package_get_config (pkg, "LogDir") == NULL)
235 return TRUE;
236
237 /* overwrite old log */
238 logdir_char = g_strdup_printf ("%s/%c",
239 asb_package_get_config (pkg, "LogDir"),
240 g_ascii_tolower (priv->name[0]));
241 if (!asb_utils_ensure_exists (logdir_char, error))
242 return FALSE;
243 priv->log_written_len = priv->log->len;
244 logfile = g_strdup_printf ("%s/%s.log", logdir_char, priv->name);
245 return g_file_set_contents (logfile, priv->log->str, -1, error);
246 }
247
248 /**
249 * asb_package_get_filename:
250 * @pkg: A #AsbPackage
251 *
252 * Gets the filename of the package.
253 *
254 * Returns: utf8 filename
255 *
256 * Since: 0.1.0
257 **/
258 const gchar *
asb_package_get_filename(AsbPackage * pkg)259 asb_package_get_filename (AsbPackage *pkg)
260 {
261 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
262 return priv->filename;
263 }
264
265 /**
266 * asb_package_get_kind:
267 * @pkg: A #AsbPackage
268 *
269 * Gets the kind of the package.
270 *
271 * Returns: a #AsbPackageKind
272 *
273 * Since: 0.2.5
274 **/
275 AsbPackageKind
asb_package_get_kind(AsbPackage * pkg)276 asb_package_get_kind (AsbPackage *pkg)
277 {
278 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
279 return priv->kind;
280 }
281
282 /**
283 * asb_package_get_epoch:
284 * @pkg: A #AsbPackage
285 *
286 * Gets the epoch of the package.
287 *
288 * Returns: a #AsbPackageKind
289 *
290 * Since: 0.5.6
291 **/
292 guint
asb_package_get_epoch(AsbPackage * pkg)293 asb_package_get_epoch (AsbPackage *pkg)
294 {
295 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
296 return priv->epoch;
297 }
298
299 /**
300 * asb_package_get_basename:
301 * @pkg: A #AsbPackage
302 *
303 * Gets the package basename.
304 *
305 * Returns: utf8 string
306 *
307 * Since: 0.1.0
308 **/
309 const gchar *
asb_package_get_basename(AsbPackage * pkg)310 asb_package_get_basename (AsbPackage *pkg)
311 {
312 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
313 return priv->basename;
314 }
315
316 /**
317 * asb_package_get_name:
318 * @pkg: A #AsbPackage
319 *
320 * Gets the package name
321 *
322 * Returns: utf8 string
323 *
324 * Since: 0.1.0
325 **/
326 const gchar *
asb_package_get_name(AsbPackage * pkg)327 asb_package_get_name (AsbPackage *pkg)
328 {
329 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
330 return priv->name;
331 }
332
333 /**
334 * asb_package_get_version:
335 * @pkg: A #AsbPackage
336 *
337 * Gets the package version
338 *
339 * Returns: utf8 string
340 *
341 * Since: 0.3.5
342 **/
343 const gchar *
asb_package_get_version(AsbPackage * pkg)344 asb_package_get_version (AsbPackage *pkg)
345 {
346 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
347 return priv->version;
348 }
349
350 /**
351 * asb_package_get_release_str:
352 * @pkg: A #AsbPackage
353 *
354 * Gets the package release string
355 *
356 * Returns: utf8 string
357 *
358 * Since: 0.5.6
359 **/
360 const gchar *
asb_package_get_release_str(AsbPackage * pkg)361 asb_package_get_release_str (AsbPackage *pkg)
362 {
363 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
364 return priv->release;
365 }
366
367 /**
368 * asb_package_get_arch:
369 * @pkg: A #AsbPackage
370 *
371 * Gets the package architecture
372 *
373 * Returns: utf8 string
374 *
375 * Since: 0.3.0
376 **/
377 const gchar *
asb_package_get_arch(AsbPackage * pkg)378 asb_package_get_arch (AsbPackage *pkg)
379 {
380 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
381 return priv->arch;
382 }
383
384 /**
385 * asb_package_get_url:
386 * @pkg: A #AsbPackage
387 *
388 * Gets the package homepage URL
389 *
390 * Returns: utf8 string
391 *
392 * Since: 0.1.0
393 **/
394 const gchar *
asb_package_get_url(AsbPackage * pkg)395 asb_package_get_url (AsbPackage *pkg)
396 {
397 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
398 return priv->url;
399 }
400
401 /**
402 * asb_package_get_license:
403 * @pkg: A #AsbPackage
404 *
405 * Gets the package license.
406 *
407 * Returns: utf8 string
408 *
409 * Since: 0.1.0
410 **/
411 const gchar *
asb_package_get_license(AsbPackage * pkg)412 asb_package_get_license (AsbPackage *pkg)
413 {
414 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
415 return priv->license;
416 }
417
418 /**
419 * asb_package_get_vcs:
420 * @pkg: A #AsbPackage
421 *
422 * Gets the package version control system.
423 *
424 * Returns: utf8 string
425 *
426 * Since: 0.3.4
427 **/
428 const gchar *
asb_package_get_vcs(AsbPackage * pkg)429 asb_package_get_vcs (AsbPackage *pkg)
430 {
431 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
432 return priv->vcs;
433 }
434
435 /**
436 * asb_package_get_source:
437 * @pkg: A #AsbPackage
438 *
439 * Gets the package source nevra.
440 *
441 * Returns: utf8 string
442 *
443 * Since: 0.1.0
444 **/
445 const gchar *
asb_package_get_source(AsbPackage * pkg)446 asb_package_get_source (AsbPackage *pkg)
447 {
448 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
449 return priv->source_nevra;
450 }
451
452 /**
453 * asb_package_get_source_pkgname:
454 * @pkg: A #AsbPackage
455 *
456 * Gets the package source name.
457 *
458 * Returns: utf8 string
459 *
460 * Since: 0.2.4
461 **/
462 const gchar *
asb_package_get_source_pkgname(AsbPackage * pkg)463 asb_package_get_source_pkgname (AsbPackage *pkg)
464 {
465 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
466 return priv->source_pkgname;
467 }
468
469 /**
470 * asb_package_get_filelist:
471 * @pkg: A #AsbPackage
472 *
473 * Gets the package filelist.
474 *
475 * Returns: (transfer none) (element-type utf8): filelist
476 *
477 * Since: 0.1.0
478 **/
479 gchar **
asb_package_get_filelist(AsbPackage * pkg)480 asb_package_get_filelist (AsbPackage *pkg)
481 {
482 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
483 return priv->filelist;
484 }
485
486 /**
487 * asb_package_get_deps:
488 * @pkg: A #AsbPackage
489 *
490 * Get the package dependency list.
491 *
492 * Returns: (transfer none) (element-type utf8): deplist
493 *
494 * Since: 0.3.5
495 **/
496 GPtrArray *
asb_package_get_deps(AsbPackage * pkg)497 asb_package_get_deps (AsbPackage *pkg)
498 {
499 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
500 return priv->deps;
501 }
502
503 /**
504 * asb_package_set_kind:
505 * @pkg: A #AsbPackage
506 * @kind: A #AsbPackageKind
507 *
508 * Sets the package kind.
509 *
510 * Since: 0.2.5
511 **/
512 void
asb_package_set_kind(AsbPackage * pkg,AsbPackageKind kind)513 asb_package_set_kind (AsbPackage *pkg, AsbPackageKind kind)
514 {
515 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
516 priv->kind = kind;
517 }
518
519 /**
520 * asb_package_set_name:
521 * @pkg: A #AsbPackage
522 * @name: package name
523 *
524 * Sets the package name.
525 *
526 * Since: 0.1.0
527 **/
528 void
asb_package_set_name(AsbPackage * pkg,const gchar * name)529 asb_package_set_name (AsbPackage *pkg, const gchar *name)
530 {
531 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
532 g_free (priv->name);
533 priv->name = g_strdup (name);
534 }
535
536 /**
537 * asb_package_set_version:
538 * @pkg: A #AsbPackage
539 * @version: package version
540 *
541 * Sets the package version.
542 *
543 * Since: 0.1.0
544 **/
545 void
asb_package_set_version(AsbPackage * pkg,const gchar * version)546 asb_package_set_version (AsbPackage *pkg, const gchar *version)
547 {
548 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
549 g_free (priv->version);
550 priv->version = g_strdup (version);
551 }
552
553 /**
554 * asb_package_set_release:
555 * @pkg: A #AsbPackage
556 * @release: package release
557 *
558 * Sets the package release.
559 *
560 * Since: 0.1.0
561 **/
562 void
asb_package_set_release(AsbPackage * pkg,const gchar * release)563 asb_package_set_release (AsbPackage *pkg, const gchar *release)
564 {
565 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
566 g_free (priv->release);
567 priv->release = g_strdup (release);
568 }
569
570 /**
571 * asb_package_set_arch:
572 * @pkg: A #AsbPackage
573 * @arch: package architecture
574 *
575 * Sets the package architecture.
576 *
577 * Since: 0.1.0
578 **/
579 void
asb_package_set_arch(AsbPackage * pkg,const gchar * arch)580 asb_package_set_arch (AsbPackage *pkg, const gchar *arch)
581 {
582 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
583 g_free (priv->arch);
584 priv->arch = g_strdup (arch);
585 }
586
587 /**
588 * asb_package_set_epoch:
589 * @pkg: A #AsbPackage
590 * @epoch: epoch, or 0 for unset
591 *
592 * Sets the package epoch
593 *
594 * Since: 0.1.0
595 **/
596 void
asb_package_set_epoch(AsbPackage * pkg,guint epoch)597 asb_package_set_epoch (AsbPackage *pkg, guint epoch)
598 {
599 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
600 priv->epoch = epoch;
601 }
602
603 /**
604 * asb_package_set_url:
605 * @pkg: A #AsbPackage
606 * @url: homepage URL
607 *
608 * Sets the package URL.
609 *
610 * Since: 0.1.0
611 **/
612 void
asb_package_set_url(AsbPackage * pkg,const gchar * url)613 asb_package_set_url (AsbPackage *pkg, const gchar *url)
614 {
615 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
616 g_free (priv->url);
617 priv->url = g_strdup (url);
618 }
619
620 /**
621 * asb_package_set_license:
622 * @pkg: A #AsbPackage
623 * @license: license string
624 *
625 * Sets the package license.
626 *
627 * Since: 0.1.0
628 **/
629 void
asb_package_set_license(AsbPackage * pkg,const gchar * license)630 asb_package_set_license (AsbPackage *pkg, const gchar *license)
631 {
632 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
633 g_free (priv->license);
634 priv->license = g_strdup (license);
635 }
636
637 /**
638 * asb_package_set_vcs:
639 * @pkg: A #AsbPackage
640 * @vcs: vcs string
641 *
642 * Sets the package version control system.
643 *
644 * Since: 0.3.4
645 **/
646 void
asb_package_set_vcs(AsbPackage * pkg,const gchar * vcs)647 asb_package_set_vcs (AsbPackage *pkg, const gchar *vcs)
648 {
649 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
650 g_free (priv->vcs);
651 priv->vcs = g_strdup (vcs);
652 }
653
654 /**
655 * asb_package_set_source:
656 * @pkg: A #AsbPackage
657 * @source: source string, e.g. the srpm nevra
658 *
659 * Sets the package source name, which is usually the parent of a set of
660 * subpackages.
661 *
662 * Since: 0.1.0
663 **/
664 void
asb_package_set_source(AsbPackage * pkg,const gchar * source)665 asb_package_set_source (AsbPackage *pkg, const gchar *source)
666 {
667 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
668 g_free (priv->source_nevra);
669 priv->source_nevra = g_strdup (source);
670 }
671
672 /**
673 * asb_package_set_source_pkgname:
674 * @pkg: A #AsbPackage
675 * @source_pkgname: source string, e.g. the srpm name
676 *
677 * Sets the package source name, which is usually the parent of a set of
678 * subpackages.
679 *
680 * Since: 0.2.4
681 **/
682 void
asb_package_set_source_pkgname(AsbPackage * pkg,const gchar * source_pkgname)683 asb_package_set_source_pkgname (AsbPackage *pkg, const gchar *source_pkgname)
684 {
685 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
686 g_free (priv->source_pkgname);
687 priv->source_pkgname = g_strdup (source_pkgname);
688 }
689
690 /**
691 * asb_package_add_dep:
692 * @pkg: A #AsbPackage
693 * @dep: package dep
694 *
695 * Add a package dependency.
696 *
697 * Since: 0.3.5
698 **/
699 void
asb_package_add_dep(AsbPackage * pkg,const gchar * dep)700 asb_package_add_dep (AsbPackage *pkg, const gchar *dep)
701 {
702 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
703 g_ptr_array_add (priv->deps, g_strdup (dep));
704 }
705
706 /**
707 * asb_package_set_filelist:
708 * @pkg: A #AsbPackage
709 * @filelist: package filelist
710 *
711 * Sets the package filelist.
712 *
713 * Since: 0.1.0
714 **/
715 void
asb_package_set_filelist(AsbPackage * pkg,gchar ** filelist)716 asb_package_set_filelist (AsbPackage *pkg, gchar **filelist)
717 {
718 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
719 g_strfreev (priv->filelist);
720 priv->filelist = g_strdupv (filelist);
721 }
722
723 /**
724 * asb_package_get_nevr:
725 * @pkg: A #AsbPackage
726 *
727 * Gets the package NEVR.
728 *
729 * Returns: utf8 string
730 *
731 * Since: 0.1.0
732 **/
733 const gchar *
asb_package_get_nevr(AsbPackage * pkg)734 asb_package_get_nevr (AsbPackage *pkg)
735 {
736 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
737 if (priv->nevr == NULL) {
738 if (priv->epoch == 0) {
739 priv->nevr = g_strdup_printf ("%s-%s-%s",
740 priv->name,
741 priv->version,
742 priv->release);
743 } else {
744 priv->nevr = g_strdup_printf ("%s-%u:%s-%s",
745 priv->name,
746 priv->epoch,
747 priv->version,
748 priv->release);
749 }
750 }
751 return priv->nevr;
752 }
753
754 /**
755 * asb_package_get_nevra:
756 * @pkg: A #AsbPackage
757 *
758 * Gets the package NEVRA.
759 *
760 * Returns: utf8 string
761 *
762 * Since: 0.3.0
763 **/
764 const gchar *
asb_package_get_nevra(AsbPackage * pkg)765 asb_package_get_nevra (AsbPackage *pkg)
766 {
767 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
768 if (priv->nevra == NULL) {
769 if (priv->epoch == 0) {
770 priv->nevra = g_strdup_printf ("%s-%s-%s.%s",
771 priv->name,
772 priv->version,
773 priv->release,
774 priv->arch);
775 } else {
776 priv->nevra = g_strdup_printf ("%s-%u:%s-%s.%s",
777 priv->name,
778 priv->epoch,
779 priv->version,
780 priv->release,
781 priv->arch);
782 }
783 }
784 return priv->nevra;
785 }
786
787 /**
788 * asb_package_get_evr:
789 * @pkg: A #AsbPackage
790 *
791 * Gets the package EVR.
792 *
793 * Returns: utf8 string
794 *
795 * Since: 0.1.0
796 **/
797 const gchar *
asb_package_get_evr(AsbPackage * pkg)798 asb_package_get_evr (AsbPackage *pkg)
799 {
800 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
801 if (priv->evr == NULL) {
802 if (priv->epoch == 0) {
803 priv->evr = g_strdup_printf ("%s-%s",
804 priv->version,
805 priv->release);
806 } else {
807 priv->evr = g_strdup_printf ("%u:%s-%s",
808 priv->epoch,
809 priv->version,
810 priv->release);
811 }
812 }
813 return priv->evr;
814 }
815
816 static void
asb_package_class_init(AsbPackageClass * klass)817 asb_package_class_init (AsbPackageClass *klass)
818 {
819 GObjectClass *object_class = G_OBJECT_CLASS (klass);
820 object_class->finalize = asb_package_finalize;
821 }
822
823 static void
asb_package_guess_from_filename(AsbPackage * pkg)824 asb_package_guess_from_filename (AsbPackage *pkg)
825 {
826 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
827 g_autofree gchar *tmp = NULL;
828 gchar *at;
829
830 /* remove .rpm extension */
831 tmp = g_path_get_basename (priv->filename);
832 at = g_strrstr (tmp, ".rpm");
833 if (at == NULL)
834 return;
835 *at = '\0';
836
837 /* get arch */
838 at = g_strrstr (tmp, ".");
839 if (at == NULL)
840 return;
841 priv->arch = g_strdup (at + 1);
842 *at = '\0';
843
844 /* get release */
845 at = g_strrstr (tmp, "-");
846 if (at == NULL)
847 return;
848 priv->release = g_strdup (at + 1);
849 *at = '\0';
850
851 /* get version */
852 at = g_strrstr (tmp, "-");
853 if (at == NULL)
854 return;
855 priv->version = g_strdup (at + 1);
856 *at = '\0';
857
858 /* get name */
859 priv->name = g_strdup (tmp);
860 }
861
862 /**
863 * asb_package_set_filename:
864 * @pkg: A #AsbPackage
865 * @filename: package filename
866 *
867 * Sets the package filename.
868 *
869 * Since: 0.3.5
870 **/
871 void
asb_package_set_filename(AsbPackage * pkg,const gchar * filename)872 asb_package_set_filename (AsbPackage *pkg, const gchar *filename)
873 {
874 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
875 g_free (priv->basename);
876 g_free (priv->filename);
877 priv->basename = g_path_get_basename (filename);
878 priv->filename = g_strdup (filename);
879
880 /* this only works for correctly formatted file names */
881 asb_package_guess_from_filename (pkg);
882 }
883
884 /**
885 * asb_package_open:
886 * @pkg: A #AsbPackage
887 * @filename: package filename
888 * @error: A #GError or %NULL
889 *
890 * Opens a package and parses the contents.
891 * As little i/o should be done at this point, and implementations
892 * should rely on asb_package_ensure() to set data.
893 *
894 * Returns: %TRUE for success, %FALSE otherwise
895 *
896 * Since: 0.1.0
897 **/
898 gboolean
asb_package_open(AsbPackage * pkg,const gchar * filename,GError ** error)899 asb_package_open (AsbPackage *pkg, const gchar *filename, GError **error)
900 {
901 AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg);
902 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
903
904 /* already open */
905 if (priv->is_open)
906 return TRUE;
907 priv->is_open = TRUE;
908
909 /* save filename if not already set */
910 if (priv->filename == NULL)
911 asb_package_set_filename (pkg, filename);
912
913 /* call distro-specific method */
914 if (klass->open != NULL)
915 return klass->open (pkg, filename, error);
916 return TRUE;
917 }
918
919 /**
920 * asb_package_close:
921 * @pkg: A #AsbPackage
922 * @error: A #GError or %NULL
923 *
924 * Closes a package, which can be re-opened if required.
925 *
926 * Returns: %TRUE for success, %FALSE otherwise
927 *
928 * Since: 0.3.5
929 **/
930 gboolean
asb_package_close(AsbPackage * pkg,GError ** error)931 asb_package_close (AsbPackage *pkg, GError **error)
932 {
933 AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg);
934 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
935
936 /* already closed */
937 if (!priv->is_open)
938 return TRUE;
939 priv->is_open = FALSE;
940
941 /* call distro-specific method */
942 if (klass->close != NULL)
943 return klass->close (pkg, error);
944 return TRUE;
945 }
946
947 /**
948 * asb_package_ensure:
949 * @pkg: A #AsbPackage
950 * @flags: #AsbPackageEnsureFlags
951 * @error: A #GError or %NULL
952 *
953 * Ensures data exists.
954 *
955 * Returns: %TRUE for success, %FALSE otherwise
956 *
957 * Since: 0.3.0
958 **/
959 gboolean
asb_package_ensure(AsbPackage * pkg,AsbPackageEnsureFlags flags,GError ** error)960 asb_package_ensure (AsbPackage *pkg,
961 AsbPackageEnsureFlags flags,
962 GError **error)
963 {
964 AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg);
965 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
966
967 /* reopen as required */
968 if (!priv->is_open) {
969 if (!asb_package_open (pkg, priv->filename, error))
970 return FALSE;
971 }
972
973 /* this is recounted */
974 if (flags & ASB_PACKAGE_ENSURE_DEPS)
975 priv->deps_refcount++;
976 if (flags & ASB_PACKAGE_ENSURE_FILES)
977 priv->filelist_refcount++;
978
979 /* clear flags */
980 if (priv->name != NULL)
981 flags &= ~ASB_PACKAGE_ENSURE_NEVRA;
982 if (priv->license != NULL)
983 flags &= ~ASB_PACKAGE_ENSURE_LICENSE;
984 if (priv->vcs != NULL)
985 flags &= ~ASB_PACKAGE_ENSURE_VCS;
986 if (priv->url != NULL)
987 flags &= ~ASB_PACKAGE_ENSURE_URL;
988 if (priv->source_pkgname != NULL)
989 flags &= ~ASB_PACKAGE_ENSURE_SOURCE;
990 if (priv->filelist != NULL)
991 flags &= ~ASB_PACKAGE_ENSURE_FILES;
992 if (priv->deps->len > 0)
993 flags &= ~ASB_PACKAGE_ENSURE_DEPS;
994 if (priv->releases->len > 0)
995 flags &= ~ASB_PACKAGE_ENSURE_RELEASES;
996
997 /* nothing to do! */
998 if (flags == ASB_PACKAGE_ENSURE_NONE)
999 return TRUE;
1000
1001 /* call distro-specific method */
1002 if (klass->ensure != NULL)
1003 return klass->ensure (pkg, flags, error);
1004 return TRUE;
1005 }
1006
1007 /**
1008 * asb_package_clear:
1009 * @pkg: A #AsbPackage
1010 * @flags: #AsbPackageEnsureFlags
1011 *
1012 * Deallocates previously ensured data.
1013 *
1014 * Since: 0.3.5
1015 **/
1016 void
asb_package_clear(AsbPackage * pkg,AsbPackageEnsureFlags flags)1017 asb_package_clear (AsbPackage *pkg, AsbPackageEnsureFlags flags)
1018 {
1019 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1020
1021 /* this is recounted */
1022 if (flags & ASB_PACKAGE_ENSURE_DEPS) {
1023 if (priv->deps_refcount > 0 && --priv->deps_refcount == 0)
1024 g_ptr_array_set_size (priv->deps, 0);
1025 }
1026 if (flags & ASB_PACKAGE_ENSURE_FILES) {
1027 if (priv->filelist_refcount > 0 && --priv->filelist_refcount == 0) {
1028 g_strfreev (priv->filelist);
1029 priv->filelist = NULL;
1030 }
1031 }
1032 }
1033
1034 /**
1035 * asb_package_explode:
1036 * @pkg: A #AsbPackage
1037 * @dir: directory to explode into
1038 * @glob: (element-type utf8): the glob list, or %NULL
1039 * @error: A #GError or %NULL
1040 *
1041 * Decompresses a package into a directory, optionally using a glob list.
1042 *
1043 * Returns: %TRUE for success, %FALSE otherwise
1044 *
1045 * Since: 0.1.0
1046 **/
1047 gboolean
asb_package_explode(AsbPackage * pkg,const gchar * dir,GPtrArray * glob,GError ** error)1048 asb_package_explode (AsbPackage *pkg,
1049 const gchar *dir,
1050 GPtrArray *glob,
1051 GError **error)
1052 {
1053 AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg);
1054 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1055 if (klass->explode != NULL)
1056 return klass->explode (pkg, dir, glob, error);
1057 return asb_utils_explode (priv->filename, dir, glob, error);
1058 }
1059
1060 /**
1061 * asb_package_set_config:
1062 * @pkg: A #AsbPackage
1063 * @key: utf8 string
1064 * @value: utf8 string
1065 *
1066 * Sets a config attribute on a package.
1067 *
1068 * Since: 0.1.0
1069 **/
1070 void
asb_package_set_config(AsbPackage * pkg,const gchar * key,const gchar * value)1071 asb_package_set_config (AsbPackage *pkg, const gchar *key, const gchar *value)
1072 {
1073 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1074 g_hash_table_insert (priv->configs, g_strdup (key), g_strdup (value));
1075 }
1076
1077 /**
1078 * asb_package_get_config:
1079 * @pkg: A #AsbPackage
1080 * @key: utf8 string
1081 *
1082 * Gets a config attribute from a package.
1083 *
1084 * Returns: utf8 string
1085 *
1086 * Since: 0.1.0
1087 **/
1088 const gchar *
asb_package_get_config(AsbPackage * pkg,const gchar * key)1089 asb_package_get_config (AsbPackage *pkg, const gchar *key)
1090 {
1091 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1092 return g_hash_table_lookup (priv->configs, key);
1093 }
1094
1095 /**
1096 * asb_package_get_releases:
1097 * @pkg: A #AsbPackage
1098 *
1099 * Gets the releases of the package.
1100 *
1101 * Returns: (transfer none) (element-type AsRelease): the release data
1102 *
1103 * Since: 0.1.0
1104 **/
1105 GPtrArray *
asb_package_get_releases(AsbPackage * pkg)1106 asb_package_get_releases (AsbPackage *pkg)
1107 {
1108 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1109 return priv->releases;
1110 }
1111
1112 /**
1113 * asb_package_compare:
1114 * @pkg1: A #AsbPackage
1115 * @pkg2: A #AsbPackage
1116 *
1117 * Compares one package with another.
1118 *
1119 * Returns: +1 for @pkg1 newer, 0 for the same and -1 if @pkg2 is newer
1120 *
1121 * Since: 0.1.0
1122 **/
1123 gint
asb_package_compare(AsbPackage * pkg1,AsbPackage * pkg2)1124 asb_package_compare (AsbPackage *pkg1, AsbPackage *pkg2)
1125 {
1126 AsbPackagePrivate *priv1 = GET_PRIVATE (pkg1);
1127 AsbPackagePrivate *priv2 = GET_PRIVATE (pkg2);
1128 AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg1);
1129 gint rc;
1130
1131 /* class-specific compare method */
1132 if (klass->compare != NULL)
1133 return klass->compare (pkg1, pkg2);
1134
1135 /* check name */
1136 rc = g_strcmp0 (priv1->name, priv2->name);
1137 if (rc != 0)
1138 return rc;
1139
1140 /* check epoch */
1141 if (priv1->epoch < priv2->epoch)
1142 return -1;
1143 if (priv1->epoch > priv2->epoch)
1144 return 1;
1145
1146 /* check version */
1147 rc = as_utils_vercmp_full (priv1->version, priv2->version, AS_VERSION_COMPARE_FLAG_NONE);
1148 if (rc != 0)
1149 return rc;
1150
1151 /* check release */
1152 rc = as_utils_vercmp_full (priv1->release, priv2->release, AS_VERSION_COMPARE_FLAG_NONE);
1153 if (rc != 0)
1154 return rc;
1155
1156 /* check arch */
1157 return g_strcmp0 (priv1->arch, priv2->arch);
1158 }
1159
1160 /**
1161 * asb_package_get_release:
1162 * @pkg: A #AsbPackage
1163 * @version: package version
1164 *
1165 * Gets the release for a specific version.
1166 *
1167 * Returns: (transfer none): an #AsRelease, or %NULL for not found
1168 *
1169 * Since: 0.1.0
1170 **/
1171 AsRelease *
asb_package_get_release(AsbPackage * pkg,const gchar * version)1172 asb_package_get_release (AsbPackage *pkg, const gchar *version)
1173 {
1174 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1175 return g_hash_table_lookup (priv->releases_hash, version);
1176 }
1177
1178 /**
1179 * asb_package_add_release:
1180 * @pkg: A #AsbPackage
1181 * @version: a package version
1182 * @release: a package release
1183 *
1184 * Adds a (downstream) release to a package.
1185 *
1186 * Since: 0.1.0
1187 **/
1188 void
asb_package_add_release(AsbPackage * pkg,const gchar * version,AsRelease * release)1189 asb_package_add_release (AsbPackage *pkg,
1190 const gchar *version,
1191 AsRelease *release)
1192 {
1193 AsbPackagePrivate *priv = GET_PRIVATE (pkg);
1194 g_hash_table_insert (priv->releases_hash,
1195 g_strdup (version),
1196 g_object_ref (release));
1197 g_ptr_array_add (priv->releases, g_object_ref (release));
1198 }
1199
1200 /**
1201 * asb_package_new:
1202 *
1203 * Creates a new %AsbPackage.
1204 *
1205 * You don't need to use this function unless you want a memory-backed package
1206 * for testing purposes.
1207 *
1208 * Returns: a package
1209 *
1210 * Since: 0.2.2
1211 **/
1212 AsbPackage *
asb_package_new(void)1213 asb_package_new (void)
1214 {
1215 AsbPackage *pkg;
1216 pkg = g_object_new (ASB_TYPE_PACKAGE, NULL);
1217 return ASB_PACKAGE (pkg);
1218 }
1219