1.1 --- a/app-manager/Makefile.am Tue Jun 29 10:09:34 2021 +0100
1.2 +++ b/app-manager/Makefile.am Tue Apr 25 17:41:00 2023 +0100
1.3 @@ -3,14 +3,15 @@
1.4
1.5 bin_PROGRAMS=app-manager fetch
1.6 app_manager_SOURCES=app-manager.c app-manager.h packagelist.c applications.c \
1.7 - localmedia.c localmedia.h setup.c update.c default_action.c
1.8 + localmedia.c localmedia.h setup.c update.c default_action.c \
1.9 + localdistributions.c localdistributions.h
1.10 fetch_SOURCES=fetch.c
1.11 fetch_LDADD=$(LDADD) $(FETCH_LIBS)
1.12 if HAVE_WINDRES
1.13 app_manager_SOURCES+=resources.rc app-manager.exe.manifest
1.14 endif
1.15 if PLOVER_MINGW
1.16 -app_manager_LDFLAGS=-mwindows
1.17 +#app_manager_LDFLAGS=-mwindows
1.18 endif
1.19 uidir=$(pkgdatadir)
1.20 ui_DATA=app-manager.ui
2.1 --- a/app-manager/app-manager.c Tue Jun 29 10:09:34 2021 +0100
2.2 +++ b/app-manager/app-manager.c Tue Apr 25 17:41:00 2023 +0100
2.3 @@ -32,6 +32,7 @@
2.4 #include <plover-gtk/stockicons.h>
2.5 #include "app-manager.h"
2.6 #include "localmedia.h"
2.7 +#include "localdistributions.h"
2.8
2.9 LUALIB_API int luaopen_posix(lua_State *L);
2.10
2.11 @@ -302,6 +303,17 @@
2.12 #ifdef WIN32
2.13 prefix=g_win32_get_package_installation_directory_of_module(NULL);
2.14 #endif
2.15 + if (prefix)
2.16 + {
2.17 + /*
2.18 + * Note that this won't generally work if the application is stored
2.19 + * on a removable device. If you need the logfile, copy it to the
2.20 + * harddisk first.
2.21 + */
2.22 + s=g_strconcat(prefix,"/var/log/init",NULL);
2.23 + plover_log_open(s);
2.24 + g_free(s);
2.25 + }
2.26 install_icons();
2.27 ui=gtk_builder_new();
2.28 if (!g_file_get_contents("app-manager.ui",&contents,&len,&err) &&
2.29 @@ -384,15 +396,21 @@
2.30 w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
2.31 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE);
2.32 }
2.33 + g_clear_object(&set);
2.34 applications=plover_applications_model_new(installed);
2.35 set_package_model(applications);
2.36 w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
2.37 + if (prefix)
2.38 + {
2.39 + s=g_strconcat(prefix,"/var/log/interactive",NULL);
2.40 + plover_log_open(s);
2.41 + g_free(s);
2.42 + }
2.43 gtk_widget_show(w);
2.44 started=TRUE;
2.45 }
2.46 if (started)
2.47 gtk_main();
2.48 - g_clear_object(&set);
2.49 objects=gtk_builder_get_objects(ui);
2.50 for(lnk=objects;lnk;lnk=lnk->next)
2.51 if (GTK_IS_WIDGET(lnk->data) &&
2.52 @@ -454,6 +472,108 @@
2.53 set_package_model(location);
2.54 }
2.55
2.56 +gboolean open_database(const char *uri,const char *destination,GError **err)
2.57 +{
2.58 + gboolean retval;
2.59 + GSList *sets,*lnk;
2.60 + GtkWidget *w;
2.61 + PloverPackageSet *set;
2.62 + if (!g_strcmp0(uri,razor_get_database_uri()))
2.63 + return TRUE;
2.64 + if (relocations)
2.65 + {
2.66 + razor_relocations_destroy(relocations);
2.67 + relocations=NULL;
2.68 + }
2.69 + razor_set_database_uri(uri);
2.70 + if (destination)
2.71 + {
2.72 + relocations=razor_relocations_create();
2.73 + razor_relocations_add(relocations,"/usr",destination);
2.74 + }
2.75 + sets=plover_package_store_get_sets(PLOVER_PACKAGE_STORE(installed));
2.76 + sets=g_slist_copy(sets);
2.77 + for(lnk=sets;lnk;lnk=lnk->next)
2.78 + {
2.79 + set=lnk->data;
2.80 + plover_package_store_remove_set(PLOVER_PACKAGE_STORE(installed),set);
2.81 + }
2.82 + g_slist_free(sets);
2.83 + set=plover_package_set_new();
2.84 + retval=plover_package_set_open(set,"",TRUE,err);
2.85 + plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set);
2.86 + g_object_unref(set);
2.87 + w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
2.88 + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
2.89 + !!plover_package_set_get_no_details(set));
2.90 + return retval;
2.91 +}
2.92 +
2.93 +G_MODULE_EXPORT void on_open_database(GtkWidget *widget)
2.94 +{
2.95 + gboolean have_local_distributions;
2.96 + const char *database_uri;
2.97 + gchar *uri,*s;
2.98 + GList *cells;
2.99 + GtkWidget *w,*radio_global,*radio_local,*combo,*dialog;
2.100 + GtkCellRenderer *cell;
2.101 + GtkTreeModel *local;
2.102 + GtkTreeIter iter;
2.103 + dialog=GTK_WIDGET(gtk_builder_get_object(ui,"OpenDatabase"));
2.104 + local=GTK_TREE_MODEL(plover_local_distributions_new());
2.105 + have_local_distributions=!!gtk_tree_model_iter_n_children(local,NULL);
2.106 + radio_global=GTK_WIDGET(gtk_builder_get_object(ui,"distribution_global"));
2.107 + radio_local=GTK_WIDGET(gtk_builder_get_object(ui,"distribution_local"));
2.108 + gtk_widget_set_sensitive(radio_local,have_local_distributions);
2.109 + w=GTK_WIDGET(gtk_builder_get_object(ui,"local_databases_label"));
2.110 + gtk_widget_set_sensitive(w,have_local_distributions);
2.111 + combo=GTK_WIDGET(gtk_builder_get_object(ui,"local_databases"));
2.112 + gtk_combo_box_set_model(GTK_COMBO_BOX(combo),local);
2.113 + gtk_widget_set_sensitive(w,have_local_distributions);
2.114 + database_uri=razor_get_database_uri();
2.115 + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo),NULL);
2.116 + if (gtk_tree_model_get_iter_first(local,&iter))
2.117 + do
2.118 + {
2.119 + gtk_tree_model_get(local,&iter,
2.120 + PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN,&s,-1);
2.121 + if (!g_strcmp0(s,database_uri))
2.122 + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo),&iter);
2.123 + g_free(s);
2.124 + } while(gtk_tree_model_iter_next(local,&iter));
2.125 + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo),&iter))
2.126 + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_local),TRUE);
2.127 + else
2.128 + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_global),TRUE);
2.129 + cells=gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(combo));
2.130 + if (cells)
2.131 + g_list_free(cells);
2.132 + else
2.133 + {
2.134 + cell=gtk_cell_renderer_text_new();
2.135 + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),cell,TRUE);
2.136 + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo),cell,"text",
2.137 + PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN);
2.138 + }
2.139 + if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT)
2.140 + {
2.141 + show_busy_cursor(TRUE);
2.142 + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_global)))
2.143 + open_database(NULL,prefix,NULL);
2.144 + else if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo),&iter))
2.145 + {
2.146 + gtk_tree_model_get(local,&iter,
2.147 + PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN,&uri,
2.148 + PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN,&s,-1);
2.149 + open_database(uri,s,NULL);
2.150 + g_free(uri);
2.151 + g_free(s);
2.152 + }
2.153 + show_busy_cursor(FALSE);
2.154 + }
2.155 + gtk_widget_hide(dialog);
2.156 +}
2.157 +
2.158 G_MODULE_EXPORT void on_open_location(GtkWidget *widget)
2.159 {
2.160 GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
2.161 @@ -546,6 +666,86 @@
2.162 show_busy_cursor(FALSE);
2.163 }
2.164
2.165 +G_MODULE_EXPORT void on_open_archive(GtkWidget *widget)
2.166 +{
2.167 + GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
2.168 + GtkWidget *dialog;
2.169 + GFile *file,*parent;
2.170 + GFileInfo *fi;
2.171 + GMount *mount;
2.172 + gchar *path,*name;
2.173 + PloverPackageSet *set;
2.174 + GSList *sets;
2.175 + GError *err=NULL;
2.176 + dialog=gtk_file_chooser_dialog_new("Open Achive",GTK_WINDOW(w),
2.177 + GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_CANCEL,
2.178 + GTK_RESPONSE_CANCEL,GTK_STOCK_OPEN,GTK_RESPONSE_ACCEPT,NULL);
2.179 + if (gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_ACCEPT)
2.180 + {
2.181 + show_busy_cursor(TRUE);
2.182 + path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
2.183 + set=plover_package_set_new_from_yum(path,relocations,&err);
2.184 + if (set)
2.185 + {
2.186 + if (!location)
2.187 + location=GTK_TREE_MODEL(plover_package_store_new());
2.188 + while((sets=
2.189 + plover_package_store_get_sets(PLOVER_PACKAGE_STORE(location))))
2.190 + plover_package_store_remove_set(PLOVER_PACKAGE_STORE(location),
2.191 + PLOVER_PACKAGE_SET(sets->data));
2.192 + plover_package_store_add_set(PLOVER_PACKAGE_STORE(location),set);
2.193 + g_object_unref(set);
2.194 + w=GTK_WIDGET(gtk_builder_get_object(ui,"LocationButton"));
2.195 + file=g_file_new_for_path(path);
2.196 + parent=g_file_get_parent(file);
2.197 + if (parent)
2.198 + {
2.199 + g_object_unref(parent);
2.200 + mount=NULL;
2.201 + }
2.202 + else
2.203 + mount=g_file_find_enclosing_mount(file,NULL,NULL);
2.204 + if (mount)
2.205 + {
2.206 + name=g_mount_get_name(mount);
2.207 + g_object_unref(mount);
2.208 + }
2.209 + else
2.210 + {
2.211 + fi=g_file_query_info(file,
2.212 + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
2.213 + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
2.214 + if (fi)
2.215 + {
2.216 + name=g_strdup(g_file_info_get_display_name(fi));
2.217 + g_object_unref(fi);
2.218 + }
2.219 + else
2.220 + name=g_filename_display_basename(path);
2.221 + g_object_unref(file);
2.222 + }
2.223 + gtk_tool_button_set_label(GTK_TOOL_BUTTON(w),name);
2.224 + g_free(name);
2.225 + gtk_widget_show(w);
2.226 + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(w),TRUE);
2.227 + }
2.228 + else
2.229 + {
2.230 + gtk_widget_destroy(dialog);
2.231 + dialog=gtk_message_dialog_new(GTK_WINDOW(w),
2.232 + GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,
2.233 + GTK_BUTTONS_CLOSE,"Error loading repository '%s'",path);
2.234 + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
2.235 + "%s",err->message);
2.236 + gtk_dialog_run(GTK_DIALOG(dialog));
2.237 + g_error_free(err);
2.238 + }
2.239 + g_free(path);
2.240 + show_busy_cursor(FALSE);
2.241 + }
2.242 + gtk_widget_destroy(dialog);
2.243 +}
2.244 +
2.245 G_MODULE_EXPORT void on_help_about(GtkWidget *widget)
2.246 {
2.247 GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
3.1 --- a/app-manager/app-manager.ui Tue Jun 29 10:09:34 2021 +0100
3.2 +++ b/app-manager/app-manager.ui Tue Apr 25 17:41:00 2023 +0100
3.3 @@ -1,61 +1,76 @@
3.4 -<?xml version="1.0"?>
3.5 +<?xml version="1.0" encoding="UTF-8"?>
3.6 <interface>
3.7 <requires lib="gtk+" version="2.16"/>
3.8 <!-- interface-naming-policy project-wide -->
3.9 + <object class="GtkTextBuffer" id="description"/>
3.10 + <object class="GtkImage" id="image1">
3.11 + <property name="visible">True</property>
3.12 + <property name="can_focus">False</property>
3.13 + <property name="stock">gtk-open</property>
3.14 + </object>
3.15 + <object class="GtkImage" id="image2">
3.16 + <property name="visible">True</property>
3.17 + <property name="can_focus">False</property>
3.18 + <property name="stock">gtk-cdrom</property>
3.19 + </object>
3.20 + <object class="GtkImage" id="image3">
3.21 + <property name="visible">True</property>
3.22 + <property name="can_focus">False</property>
3.23 + <property name="stock">gtk-file</property>
3.24 + </object>
3.25 + <object class="GtkImage" id="image4">
3.26 + <property name="visible">True</property>
3.27 + <property name="can_focus">False</property>
3.28 + <property name="stock">gtk-open</property>
3.29 + </object>
3.30 <object class="GtkWindow" id="MainWindow">
3.31 + <property name="can_focus">False</property>
3.32 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.33 <property name="title" translatable="yes">Application Manager</property>
3.34 <property name="default_width">600</property>
3.35 <property name="default_height">400</property>
3.36 - <signal name="delete_event" handler="gtk_main_quit"/>
3.37 + <signal name="delete-event" handler="gtk_main_quit" swapped="no"/>
3.38 <child>
3.39 <object class="GtkVBox" id="vbox1">
3.40 <property name="visible">True</property>
3.41 + <property name="can_focus">False</property>
3.42 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.43 - <property name="orientation">vertical</property>
3.44 <property name="spacing">6</property>
3.45 <child>
3.46 <object class="GtkMenuBar" id="menubar1">
3.47 <property name="visible">True</property>
3.48 + <property name="can_focus">False</property>
3.49 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.50 <child>
3.51 <object class="GtkMenuItem" id="menuitem1">
3.52 <property name="visible">True</property>
3.53 + <property name="can_focus">False</property>
3.54 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.55 - <property name="label" translatable="yes">_Package</property>
3.56 + <property name="label" translatable="yes">_Database</property>
3.57 <property name="use_underline">True</property>
3.58 <child type="submenu">
3.59 - <object class="GtkMenu" id="menu1">
3.60 + <object class="GtkMenu" id="menu4">
3.61 <property name="visible">True</property>
3.62 + <property name="can_focus">False</property>
3.63 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.64 <child>
3.65 - <object class="GtkImageMenuItem" id="imagemenuitem1">
3.66 - <property name="label">Open _Location...</property>
3.67 + <object class="GtkImageMenuItem" id="imagemenuitem3">
3.68 + <property name="label">_Open...</property>
3.69 <property name="visible">True</property>
3.70 + <property name="can_focus">False</property>
3.71 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.72 - <property name="tooltip_text" translatable="yes">Open a package repository at a known location</property>
3.73 + <property name="tooltip_text" translatable="yes">Open an existing package database</property>
3.74 <property name="use_underline">True</property>
3.75 - <property name="image">image1</property>
3.76 + <property name="image">image4</property>
3.77 <property name="use_stock">False</property>
3.78 - <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
3.79 - <signal name="activate" handler="on_open_location"/>
3.80 - </object>
3.81 - </child>
3.82 - <child>
3.83 - <object class="GtkImageMenuItem" id="menuitem5">
3.84 - <property name="label" translatable="yes">_Scan local media</property>
3.85 - <property name="visible">True</property>
3.86 - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.87 - <property name="tooltip_text" translatable="yes">Scan local media for package repositories</property>
3.88 - <property name="use_underline">True</property>
3.89 - <property name="image">image2</property>
3.90 - <property name="use_stock">False</property>
3.91 - <signal name="activate" handler="on_scan_local_media"/>
3.92 + <accelerator key="o" signal="activate" modifiers="GDK_CONTROL_MASK"/>
3.93 + <signal name="activate" handler="on_open_database" swapped="no"/>
3.94 </object>
3.95 </child>
3.96 <child>
3.97 <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
3.98 <property name="visible">True</property>
3.99 + <property name="can_focus">False</property>
3.100 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.101 </object>
3.102 </child>
3.103 @@ -63,12 +78,70 @@
3.104 <object class="GtkImageMenuItem" id="imagemenuitem5">
3.105 <property name="label">gtk-quit</property>
3.106 <property name="visible">True</property>
3.107 + <property name="can_focus">False</property>
3.108 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.109 <property name="tooltip_text" translatable="yes">Quit the application manager</property>
3.110 <property name="use_underline">True</property>
3.111 <property name="use_stock">True</property>
3.112 <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
3.113 - <signal name="activate" handler="gtk_main_quit"/>
3.114 + <signal name="activate" handler="gtk_main_quit" swapped="no"/>
3.115 + </object>
3.116 + </child>
3.117 + </object>
3.118 + </child>
3.119 + </object>
3.120 + </child>
3.121 + <child>
3.122 + <object class="GtkMenuItem" id="menuitem2">
3.123 + <property name="visible">True</property>
3.124 + <property name="can_focus">False</property>
3.125 + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.126 + <property name="label" translatable="yes">_Repository</property>
3.127 + <property name="use_underline">True</property>
3.128 + <child type="submenu">
3.129 + <object class="GtkMenu" id="menu1">
3.130 + <property name="visible">True</property>
3.131 + <property name="can_focus">False</property>
3.132 + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.133 + <child>
3.134 + <object class="GtkImageMenuItem" id="imagemenuitem1">
3.135 + <property name="label">Open _Location...</property>
3.136 + <property name="visible">True</property>
3.137 + <property name="can_focus">False</property>
3.138 + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.139 + <property name="tooltip_text" translatable="yes">Open a package repository at a known location</property>
3.140 + <property name="use_underline">True</property>
3.141 + <property name="image">image1</property>
3.142 + <property name="use_stock">False</property>
3.143 + <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
3.144 + <signal name="activate" handler="on_open_location" swapped="no"/>
3.145 + </object>
3.146 + </child>
3.147 + <child>
3.148 + <object class="GtkImageMenuItem" id="menuitem5">
3.149 + <property name="label" translatable="yes">_Scan local media</property>
3.150 + <property name="visible">True</property>
3.151 + <property name="can_focus">False</property>
3.152 + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.153 + <property name="tooltip_text" translatable="yes">Scan local media for package repositories</property>
3.154 + <property name="use_underline">True</property>
3.155 + <property name="image">image2</property>
3.156 + <property name="use_stock">False</property>
3.157 + <signal name="activate" handler="on_scan_local_media" swapped="no"/>
3.158 + </object>
3.159 + </child>
3.160 + <child>
3.161 + <object class="GtkImageMenuItem" id="imagemenuitem2">
3.162 + <property name="label">Open _Archive...</property>
3.163 + <property name="visible">True</property>
3.164 + <property name="can_focus">False</property>
3.165 + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.166 + <property name="tooltip_text" translatable="yes">Open an archived package repository</property>
3.167 + <property name="use_underline">True</property>
3.168 + <property name="image">image3</property>
3.169 + <property name="use_stock">False</property>
3.170 + <accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/>
3.171 + <signal name="activate" handler="on_open_archive" swapped="no"/>
3.172 </object>
3.173 </child>
3.174 </object>
3.175 @@ -78,34 +151,38 @@
3.176 <child>
3.177 <object class="GtkMenuItem" id="menuitem3">
3.178 <property name="visible">True</property>
3.179 + <property name="can_focus">False</property>
3.180 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.181 <property name="label" translatable="yes">_View</property>
3.182 <property name="use_underline">True</property>
3.183 <child type="submenu">
3.184 <object class="GtkMenu" id="menu2">
3.185 <property name="visible">True</property>
3.186 + <property name="can_focus">False</property>
3.187 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.188 <child>
3.189 <object class="GtkRadioMenuItem" id="ViewFiles">
3.190 <property name="visible">True</property>
3.191 + <property name="can_focus">False</property>
3.192 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.193 <property name="tooltip_text" translatable="yes">Show a list of files owned by the selected package</property>
3.194 <property name="label" translatable="yes">_File list</property>
3.195 <property name="use_underline">True</property>
3.196 <property name="draw_as_radio">True</property>
3.197 - <signal name="toggled" handler="on_view_files_toggled"/>
3.198 + <signal name="toggled" handler="on_view_files_toggled" swapped="no"/>
3.199 </object>
3.200 </child>
3.201 <child>
3.202 <object class="GtkRadioMenuItem" id="menuitem6">
3.203 <property name="visible">True</property>
3.204 + <property name="can_focus">False</property>
3.205 <property name="tooltip_text" translatable="yes">Show the description etc., of the selected package</property>
3.206 <property name="label" translatable="yes">Package _details</property>
3.207 <property name="use_underline">True</property>
3.208 <property name="active">True</property>
3.209 <property name="draw_as_radio">True</property>
3.210 <property name="group">ViewFiles</property>
3.211 - <signal name="toggled" handler="on_view_details_toggled"/>
3.212 + <signal name="toggled" handler="on_view_details_toggled" swapped="no"/>
3.213 </object>
3.214 </child>
3.215 </object>
3.216 @@ -115,22 +192,25 @@
3.217 <child>
3.218 <object class="GtkMenuItem" id="menuitem4">
3.219 <property name="visible">True</property>
3.220 + <property name="can_focus">False</property>
3.221 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.222 <property name="label" translatable="yes">_Help</property>
3.223 <property name="use_underline">True</property>
3.224 <child type="submenu">
3.225 <object class="GtkMenu" id="menu3">
3.226 <property name="visible">True</property>
3.227 + <property name="can_focus">False</property>
3.228 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.229 <child>
3.230 <object class="GtkImageMenuItem" id="imagemenuitem10">
3.231 <property name="label">gtk-about</property>
3.232 <property name="visible">True</property>
3.233 + <property name="can_focus">False</property>
3.234 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.235 <property name="tooltip_text" translatable="yes">Display details about the application manager</property>
3.236 <property name="use_underline">True</property>
3.237 <property name="use_stock">True</property>
3.238 - <signal name="activate" handler="on_help_about"/>
3.239 + <signal name="activate" handler="on_help_about" swapped="no"/>
3.240 </object>
3.241 </child>
3.242 </object>
3.243 @@ -140,6 +220,7 @@
3.244 </object>
3.245 <packing>
3.246 <property name="expand">False</property>
3.247 + <property name="fill">True</property>
3.248 <property name="position">0</property>
3.249 </packing>
3.250 </child>
3.251 @@ -147,12 +228,12 @@
3.252 <object class="GtkVPaned" id="vpaned2">
3.253 <property name="visible">True</property>
3.254 <property name="can_focus">True</property>
3.255 - <property name="orientation">vertical</property>
3.256 <property name="position">215</property>
3.257 <property name="position_set">True</property>
3.258 <child>
3.259 <object class="GtkAlignment" id="alignment1">
3.260 <property name="visible">True</property>
3.261 + <property name="can_focus">False</property>
3.262 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.263 <property name="left_padding">6</property>
3.264 <property name="right_padding">6</property>
3.265 @@ -165,12 +246,13 @@
3.266 <child>
3.267 <object class="GtkVBox" id="vbox2">
3.268 <property name="visible">True</property>
3.269 + <property name="can_focus">False</property>
3.270 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.271 - <property name="orientation">vertical</property>
3.272 <property name="spacing">6</property>
3.273 <child>
3.274 <object class="GtkHBox" id="hbox1">
3.275 <property name="visible">True</property>
3.276 + <property name="can_focus">False</property>
3.277 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.278 <property name="spacing">6</property>
3.279 <child>
3.280 @@ -178,12 +260,18 @@
3.281 <property name="visible">True</property>
3.282 <property name="can_focus">True</property>
3.283 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.284 - <property name="invisible_char">●</property>
3.285 + <property name="invisible_char">●</property>
3.286 <property name="activates_default">True</property>
3.287 <property name="width_chars">10</property>
3.288 <property name="caps_lock_warning">False</property>
3.289 + <property name="primary_icon_activatable">False</property>
3.290 + <property name="secondary_icon_activatable">False</property>
3.291 + <property name="primary_icon_sensitive">True</property>
3.292 + <property name="secondary_icon_sensitive">True</property>
3.293 </object>
3.294 <packing>
3.295 + <property name="expand">True</property>
3.296 + <property name="fill">True</property>
3.297 <property name="position">0</property>
3.298 </packing>
3.299 </child>
3.300 @@ -197,7 +285,7 @@
3.301 <property name="receives_default">True</property>
3.302 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.303 <property name="use_stock">True</property>
3.304 - <signal name="clicked" handler="on_find_clicked"/>
3.305 + <signal name="clicked" handler="on_find_clicked" swapped="no"/>
3.306 </object>
3.307 <packing>
3.308 <property name="expand">False</property>
3.309 @@ -215,31 +303,35 @@
3.310 <child>
3.311 <object class="GtkHBox" id="hbox4">
3.312 <property name="visible">True</property>
3.313 + <property name="can_focus">False</property>
3.314 <child>
3.315 <object class="GtkVSeparator" id="vseparator1">
3.316 <property name="visible">True</property>
3.317 - <property name="orientation">vertical</property>
3.318 + <property name="can_focus">False</property>
3.319 </object>
3.320 <packing>
3.321 <property name="expand">False</property>
3.322 + <property name="fill">True</property>
3.323 <property name="position">0</property>
3.324 </packing>
3.325 </child>
3.326 <child>
3.327 <object class="GtkToolbar" id="toolbar1">
3.328 <property name="visible">True</property>
3.329 + <property name="can_focus">False</property>
3.330 <property name="orientation">vertical</property>
3.331 <property name="icon_size">2</property>
3.332 <property name="icon_size_set">True</property>
3.333 <child>
3.334 <object class="GtkRadioToolButton" id="toolbutton1">
3.335 <property name="visible">True</property>
3.336 + <property name="can_focus">False</property>
3.337 <property name="tooltip_text" translatable="yes">Show installed applications</property>
3.338 <property name="label" translatable="yes">_Applications</property>
3.339 <property name="use_underline">True</property>
3.340 <property name="stock_id">plover-applications</property>
3.341 <property name="active">True</property>
3.342 - <signal name="toggled" handler="on_applications_toggled"/>
3.343 + <signal name="toggled" handler="on_applications_toggled" swapped="no"/>
3.344 </object>
3.345 <packing>
3.346 <property name="expand">False</property>
3.347 @@ -249,12 +341,13 @@
3.348 <child>
3.349 <object class="GtkRadioToolButton" id="toolbutton2">
3.350 <property name="visible">True</property>
3.351 + <property name="can_focus">False</property>
3.352 <property name="tooltip_text" translatable="yes">Show all installed packages</property>
3.353 <property name="label" translatable="yes">A_ll Packages</property>
3.354 <property name="use_underline">True</property>
3.355 <property name="stock_id">gtk-index</property>
3.356 <property name="group">toolbutton1</property>
3.357 - <signal name="toggled" handler="on_all_packages_toggled"/>
3.358 + <signal name="toggled" handler="on_all_packages_toggled" swapped="no"/>
3.359 </object>
3.360 <packing>
3.361 <property name="expand">False</property>
3.362 @@ -264,6 +357,7 @@
3.363 <child>
3.364 <object class="GtkSeparatorToolItem" id="toolbutton3">
3.365 <property name="visible">True</property>
3.366 + <property name="can_focus">False</property>
3.367 </object>
3.368 <packing>
3.369 <property name="expand">False</property>
3.370 @@ -273,12 +367,13 @@
3.371 <child>
3.372 <object class="GtkRadioToolButton" id="toolbutton5">
3.373 <property name="visible">True</property>
3.374 + <property name="can_focus">False</property>
3.375 <property name="tooltip_text" translatable="yes">Show packages in repositories on local media</property>
3.376 <property name="label" translatable="yes">Local _Media</property>
3.377 <property name="use_underline">True</property>
3.378 <property name="stock_id">gtk-cdrom</property>
3.379 <property name="group">toolbutton1</property>
3.380 - <signal name="toggled" handler="on_local_media_toggled"/>
3.381 + <signal name="toggled" handler="on_local_media_toggled" swapped="no"/>
3.382 </object>
3.383 <packing>
3.384 <property name="expand">False</property>
3.385 @@ -287,11 +382,12 @@
3.386 </child>
3.387 <child>
3.388 <object class="GtkRadioToolButton" id="LocationButton">
3.389 + <property name="can_focus">False</property>
3.390 <property name="label" translatable="yes">Location</property>
3.391 <property name="use_underline">True</property>
3.392 <property name="stock_id">gtk-directory</property>
3.393 <property name="group">toolbutton1</property>
3.394 - <signal name="toggled" handler="on_location_toggled"/>
3.395 + <signal name="toggled" handler="on_location_toggled" swapped="no"/>
3.396 </object>
3.397 <packing>
3.398 <property name="expand">False</property>
3.399 @@ -300,6 +396,7 @@
3.400 </child>
3.401 <child>
3.402 <object class="GtkRadioToolButton" id="toolbutton4">
3.403 + <property name="can_focus">False</property>
3.404 <property name="tooltip_text" translatable="yes">Show updates available for installed packages</property>
3.405 <property name="label" translatable="yes">_Updates</property>
3.406 <property name="use_underline">True</property>
3.407 @@ -313,21 +410,26 @@
3.408 </child>
3.409 </object>
3.410 <packing>
3.411 + <property name="expand">True</property>
3.412 + <property name="fill">True</property>
3.413 <property name="position">1</property>
3.414 </packing>
3.415 </child>
3.416 <child>
3.417 <object class="GtkVSeparator" id="vseparator2">
3.418 <property name="visible">True</property>
3.419 - <property name="orientation">vertical</property>
3.420 + <property name="can_focus">False</property>
3.421 </object>
3.422 <packing>
3.423 <property name="expand">False</property>
3.424 + <property name="fill">True</property>
3.425 <property name="position">2</property>
3.426 </packing>
3.427 </child>
3.428 </object>
3.429 <packing>
3.430 + <property name="expand">True</property>
3.431 + <property name="fill">True</property>
3.432 <property name="position">1</property>
3.433 </packing>
3.434 </child>
3.435 @@ -369,11 +471,13 @@
3.436 <child>
3.437 <object class="GtkAlignment" id="alignment3">
3.438 <property name="visible">True</property>
3.439 + <property name="can_focus">False</property>
3.440 <property name="left_padding">6</property>
3.441 <property name="right_padding">6</property>
3.442 <child>
3.443 <object class="GtkHBox" id="ActivePackage">
3.444 <property name="visible">True</property>
3.445 + <property name="can_focus">False</property>
3.446 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.447 <property name="spacing">6</property>
3.448 <child>
3.449 @@ -391,6 +495,8 @@
3.450 </child>
3.451 </object>
3.452 <packing>
3.453 + <property name="expand">True</property>
3.454 + <property name="fill">True</property>
3.455 <property name="position">0</property>
3.456 </packing>
3.457 </child>
3.458 @@ -417,27 +523,33 @@
3.459 </child>
3.460 </object>
3.461 <packing>
3.462 + <property name="expand">True</property>
3.463 + <property name="fill">True</property>
3.464 <property name="position">1</property>
3.465 </packing>
3.466 </child>
3.467 <child>
3.468 <object class="GtkVBox" id="PackageDetails">
3.469 <property name="visible">True</property>
3.470 - <property name="orientation">vertical</property>
3.471 + <property name="can_focus">False</property>
3.472 <child>
3.473 <object class="GtkAlignment" id="HomepageBox">
3.474 <property name="visible">True</property>
3.475 + <property name="can_focus">False</property>
3.476 <property name="xscale">0</property>
3.477 <property name="yscale">0</property>
3.478 <child>
3.479 <object class="GtkHBox" id="hbox3">
3.480 <property name="visible">True</property>
3.481 + <property name="can_focus">False</property>
3.482 <child>
3.483 <object class="GtkImage" id="HomeImage">
3.484 <property name="visible">True</property>
3.485 + <property name="can_focus">False</property>
3.486 <property name="stock">gtk-home</property>
3.487 </object>
3.488 <packing>
3.489 + <property name="expand">True</property>
3.490 <property name="fill">False</property>
3.491 <property name="position">0</property>
3.492 </packing>
3.493 @@ -453,6 +565,7 @@
3.494 <property name="uri">http://www.city-occupational.co.uk/</property>
3.495 </object>
3.496 <packing>
3.497 + <property name="expand">True</property>
3.498 <property name="fill">False</property>
3.499 <property name="position">1</property>
3.500 </packing>
3.501 @@ -462,6 +575,7 @@
3.502 </object>
3.503 <packing>
3.504 <property name="expand">False</property>
3.505 + <property name="fill">True</property>
3.506 <property name="position">0</property>
3.507 </packing>
3.508 </child>
3.509 @@ -474,15 +588,18 @@
3.510 <child>
3.511 <object class="GtkViewport" id="DetailsViewport">
3.512 <property name="visible">True</property>
3.513 + <property name="can_focus">False</property>
3.514 <property name="resize_mode">queue</property>
3.515 <child>
3.516 <object class="GtkAlignment" id="DetailsAlignment">
3.517 <property name="visible">True</property>
3.518 + <property name="can_focus">False</property>
3.519 <property name="yalign">0</property>
3.520 <property name="yscale">0</property>
3.521 <child>
3.522 <object class="GtkTable" id="Details">
3.523 <property name="visible">True</property>
3.524 + <property name="can_focus">False</property>
3.525 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.526 <property name="border_width">6</property>
3.527 <property name="n_rows">2</property>
3.528 @@ -492,6 +609,7 @@
3.529 <child>
3.530 <object class="GtkLabel" id="label6">
3.531 <property name="visible">True</property>
3.532 + <property name="can_focus">False</property>
3.533 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.534 <property name="xalign">0</property>
3.535 <property name="label" translatable="yes">Architecture:</property>
3.536 @@ -499,12 +617,13 @@
3.537 </object>
3.538 <packing>
3.539 <property name="x_options">GTK_FILL</property>
3.540 - <property name="y_options"></property>
3.541 + <property name="y_options"/>
3.542 </packing>
3.543 </child>
3.544 <child>
3.545 <object class="GtkLabel" id="Architecture">
3.546 <property name="visible">True</property>
3.547 + <property name="can_focus">False</property>
3.548 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.549 <property name="xalign">0</property>
3.550 <property name="label" translatable="yes">i386</property>
3.551 @@ -515,12 +634,13 @@
3.552 <property name="left_attach">1</property>
3.553 <property name="right_attach">2</property>
3.554 <property name="x_options">GTK_FILL</property>
3.555 - <property name="y_options"></property>
3.556 + <property name="y_options"/>
3.557 </packing>
3.558 </child>
3.559 <child>
3.560 <object class="GtkLabel" id="label4">
3.561 <property name="visible">True</property>
3.562 + <property name="can_focus">False</property>
3.563 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.564 <property name="xalign">0</property>
3.565 <property name="label" translatable="yes">License:</property>
3.566 @@ -530,12 +650,13 @@
3.567 <property name="top_attach">1</property>
3.568 <property name="bottom_attach">2</property>
3.569 <property name="x_options">GTK_FILL</property>
3.570 - <property name="y_options"></property>
3.571 + <property name="y_options"/>
3.572 </packing>
3.573 </child>
3.574 <child>
3.575 <object class="GtkLabel" id="License">
3.576 <property name="visible">True</property>
3.577 + <property name="can_focus">False</property>
3.578 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.579 <property name="xalign">0</property>
3.580 <property name="label" translatable="yes">LGPL</property>
3.581 @@ -548,7 +669,7 @@
3.582 <property name="top_attach">1</property>
3.583 <property name="bottom_attach">2</property>
3.584 <property name="x_options">GTK_FILL</property>
3.585 - <property name="y_options"></property>
3.586 + <property name="y_options"/>
3.587 </packing>
3.588 </child>
3.589 </object>
3.590 @@ -559,12 +680,15 @@
3.591 </child>
3.592 </object>
3.593 <packing>
3.594 + <property name="expand">True</property>
3.595 + <property name="fill">True</property>
3.596 <property name="position">1</property>
3.597 </packing>
3.598 </child>
3.599 </object>
3.600 <packing>
3.601 <property name="expand">False</property>
3.602 + <property name="fill">True</property>
3.603 <property name="pack_type">end</property>
3.604 <property name="position">2</property>
3.605 </packing>
3.606 @@ -579,30 +703,194 @@
3.607 </child>
3.608 </object>
3.609 <packing>
3.610 + <property name="expand">True</property>
3.611 + <property name="fill">True</property>
3.612 <property name="position">1</property>
3.613 </packing>
3.614 </child>
3.615 <child>
3.616 <object class="GtkStatusbar" id="statusbar1">
3.617 <property name="visible">True</property>
3.618 + <property name="can_focus">False</property>
3.619 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3.620 <property name="spacing">2</property>
3.621 </object>
3.622 <packing>
3.623 <property name="expand">False</property>
3.624 + <property name="fill">True</property>
3.625 <property name="position">2</property>
3.626 </packing>
3.627 </child>
3.628 </object>
3.629 </child>
3.630 </object>
3.631 - <object class="GtkTextBuffer" id="description"/>
3.632 - <object class="GtkImage" id="image1">
3.633 - <property name="visible">True</property>
3.634 - <property name="stock">gtk-open</property>
3.635 - </object>
3.636 - <object class="GtkImage" id="image2">
3.637 - <property name="visible">True</property>
3.638 - <property name="stock">gtk-cdrom</property>
3.639 + <object class="GtkDialog" id="OpenDatabase">
3.640 + <property name="can_focus">False</property>
3.641 + <property name="border_width">5</property>
3.642 + <property name="title" translatable="yes">Open Database</property>
3.643 + <property name="type_hint">dialog</property>
3.644 + <property name="transient_for">MainWindow</property>
3.645 + <child internal-child="vbox">
3.646 + <object class="GtkVBox" id="dialog-vbox1">
3.647 + <property name="visible">True</property>
3.648 + <property name="can_focus">False</property>
3.649 + <property name="spacing">2</property>
3.650 + <child internal-child="action_area">
3.651 + <object class="GtkHButtonBox" id="dialog-action_area1">
3.652 + <property name="visible">True</property>
3.653 + <property name="can_focus">False</property>
3.654 + <property name="layout_style">end</property>
3.655 + <child>
3.656 + <object class="GtkButton" id="button2">
3.657 + <property name="label">gtk-cancel</property>
3.658 + <property name="visible">True</property>
3.659 + <property name="can_focus">True</property>
3.660 + <property name="receives_default">True</property>
3.661 + <property name="use_stock">True</property>
3.662 + </object>
3.663 + <packing>
3.664 + <property name="expand">False</property>
3.665 + <property name="fill">False</property>
3.666 + <property name="position">0</property>
3.667 + </packing>
3.668 + </child>
3.669 + <child>
3.670 + <object class="GtkButton" id="button3">
3.671 + <property name="label">gtk-open</property>
3.672 + <property name="visible">True</property>
3.673 + <property name="can_focus">True</property>
3.674 + <property name="receives_default">True</property>
3.675 + <property name="use_stock">True</property>
3.676 + </object>
3.677 + <packing>
3.678 + <property name="expand">False</property>
3.679 + <property name="fill">False</property>
3.680 + <property name="position">1</property>
3.681 + </packing>
3.682 + </child>
3.683 + </object>
3.684 + <packing>
3.685 + <property name="expand">True</property>
3.686 + <property name="fill">True</property>
3.687 + <property name="position">0</property>
3.688 + </packing>
3.689 + </child>
3.690 + <child>
3.691 + <object class="GtkVBox" id="vbox3">
3.692 + <property name="visible">True</property>
3.693 + <property name="can_focus">False</property>
3.694 + <property name="border_width">6</property>
3.695 + <child>
3.696 + <object class="GtkLabel" id="label1">
3.697 + <property name="visible">True</property>
3.698 + <property name="can_focus">False</property>
3.699 + <property name="xalign">0</property>
3.700 + <property name="label" translatable="yes">The primary package database for a system is known as the global
3.701 +database. If a system needs to contain multiple package sets, then
3.702 +additional ones may be configured as distribution-local databases.
3.703 +This allows packages within each package set to be independent of
3.704 +each other.
3.705 +
3.706 +If there are no distribution-local databases (or no global one), then
3.707 +this option will not be available:</property>
3.708 + </object>
3.709 + <packing>
3.710 + <property name="expand">True</property>
3.711 + <property name="fill">True</property>
3.712 + <property name="position">0</property>
3.713 + </packing>
3.714 + </child>
3.715 + <child>
3.716 + <object class="GtkVBox" id="vbox4">
3.717 + <property name="visible">True</property>
3.718 + <property name="can_focus">False</property>
3.719 + <property name="border_width">6</property>
3.720 + <child>
3.721 + <object class="GtkRadioButton" id="distribution_global">
3.722 + <property name="label" translatable="yes">Global</property>
3.723 + <property name="visible">True</property>
3.724 + <property name="can_focus">True</property>
3.725 + <property name="receives_default">False</property>
3.726 + <property name="active">True</property>
3.727 + <property name="draw_indicator">True</property>
3.728 + </object>
3.729 + <packing>
3.730 + <property name="expand">True</property>
3.731 + <property name="fill">True</property>
3.732 + <property name="position">0</property>
3.733 + </packing>
3.734 + </child>
3.735 + <child>
3.736 + <object class="GtkRadioButton" id="distribution_local">
3.737 + <property name="label" translatable="yes">Distribution-local</property>
3.738 + <property name="visible">True</property>
3.739 + <property name="can_focus">True</property>
3.740 + <property name="receives_default">False</property>
3.741 + <property name="active">True</property>
3.742 + <property name="draw_indicator">True</property>
3.743 + <property name="group">distribution_global</property>
3.744 + </object>
3.745 + <packing>
3.746 + <property name="expand">True</property>
3.747 + <property name="fill">True</property>
3.748 + <property name="position">1</property>
3.749 + </packing>
3.750 + </child>
3.751 + </object>
3.752 + <packing>
3.753 + <property name="expand">True</property>
3.754 + <property name="fill">True</property>
3.755 + <property name="position">1</property>
3.756 + </packing>
3.757 + </child>
3.758 + <child>
3.759 + <object class="GtkLabel" id="local_databases_label">
3.760 + <property name="visible">True</property>
3.761 + <property name="can_focus">False</property>
3.762 + <property name="xalign">0</property>
3.763 + <property name="label" translatable="yes">Each distribution-local database has an associated name and vendor:</property>
3.764 + </object>
3.765 + <packing>
3.766 + <property name="expand">True</property>
3.767 + <property name="fill">True</property>
3.768 + <property name="position">2</property>
3.769 + </packing>
3.770 + </child>
3.771 + <child>
3.772 + <object class="GtkVBox" id="vbox5">
3.773 + <property name="visible">True</property>
3.774 + <property name="can_focus">False</property>
3.775 + <property name="border_width">6</property>
3.776 + <child>
3.777 + <object class="GtkComboBox" id="local_databases">
3.778 + <property name="visible">True</property>
3.779 + <property name="can_focus">False</property>
3.780 + </object>
3.781 + <packing>
3.782 + <property name="expand">True</property>
3.783 + <property name="fill">True</property>
3.784 + <property name="position">0</property>
3.785 + </packing>
3.786 + </child>
3.787 + </object>
3.788 + <packing>
3.789 + <property name="expand">True</property>
3.790 + <property name="fill">True</property>
3.791 + <property name="position">3</property>
3.792 + </packing>
3.793 + </child>
3.794 + </object>
3.795 + <packing>
3.796 + <property name="expand">True</property>
3.797 + <property name="fill">True</property>
3.798 + <property name="position">1</property>
3.799 + </packing>
3.800 + </child>
3.801 + </object>
3.802 + </child>
3.803 + <action-widgets>
3.804 + <action-widget response="-6">button2</action-widget>
3.805 + <action-widget response="-3">button3</action-widget>
3.806 + </action-widgets>
3.807 </object>
3.808 </interface>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/app-manager/localdistributions.c Tue Apr 25 17:41:00 2023 +0100
4.3 @@ -0,0 +1,372 @@
4.4 +/*
4.5 + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
4.6 + * Copyright (C) 2023 J. Ali Harlow <ali@juiblex.co.uk>
4.7 + *
4.8 + * This program is free software; you can redistribute it and/or modify
4.9 + * it under the terms of the GNU General Public License as published by
4.10 + * the Free Software Foundation; either version 2 of the License, or
4.11 + * (at your option) any later version.
4.12 + *
4.13 + * This program is distributed in the hope that it will be useful,
4.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.16 + * GNU General Public License for more details.
4.17 + *
4.18 + * You should have received a copy of the GNU General Public License along
4.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
4.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
4.21 + */
4.22 +
4.23 +#include "config.h"
4.24 +#include <stdlib.h>
4.25 +#include <string.h>
4.26 +#include <glib-object.h>
4.27 +#include <gtk/gtk.h>
4.28 +#include <plover/plover.h>
4.29 +#include "localdistributions.h"
4.30 +
4.31 +#define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \
4.32 + PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp)
4.33 +
4.34 +static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS];
4.35 +
4.36 +static void
4.37 + plover_local_distributions_tree_model_init(GtkTreeModelIface *iface);
4.38 +
4.39 +G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions,
4.40 + G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
4.41 + plover_local_distributions_tree_model_init));
4.42 +
4.43 +typedef struct _PloverLocalDistribution {
4.44 + gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri;
4.45 +} PloverLocalDistribution;
4.46 +
4.47 +typedef struct _PloverLocalDistributionsPrivate {
4.48 + GList *distributions;
4.49 + int stamp;
4.50 +} PloverLocalDistributionsPrivate;
4.51 +
4.52 +#define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\
4.53 + G_TYPE_INSTANCE_GET_PRIVATE(obj,\
4.54 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
4.55 + PloverLocalDistributionsPrivate)
4.56 +
4.57 +PloverLocalDistribution *plover_local_distribution_new(const char *vendor,
4.58 + const char *distribution)
4.59 +{
4.60 + gchar *s;
4.61 + struct comps *comps;
4.62 + PloverLocalDistribution *ld;
4.63 + ld=g_new0(PloverLocalDistribution,1);
4.64 + ld->vendor=g_strdup(vendor);
4.65 + if (distribution)
4.66 + {
4.67 + ld->distribution=g_strdup(distribution);
4.68 + ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor);
4.69 + }
4.70 + else
4.71 + ld->user_friendly=g_strdup(vendor);
4.72 + comps=plover_comps_new();
4.73 + plover_comps_set_vendor(comps,vendor);
4.74 + if (distribution)
4.75 + plover_comps_set_distribution(comps,distribution);
4.76 + ld->prefix=plover_comps_get_default_prefix(comps);
4.77 + plover_comps_free(comps);
4.78 + s=g_build_filename(ld->prefix,"var","lib","razor",NULL);
4.79 + ld->database_uri=razor_path_to_uri(s);
4.80 + g_free(s);
4.81 + return ld;
4.82 +}
4.83 +
4.84 +void plover_local_distribution_free(PloverLocalDistribution *ld)
4.85 +{
4.86 + if (ld)
4.87 + {
4.88 + g_free(ld->vendor);
4.89 + g_free(ld->distribution);
4.90 + g_free(ld->prefix);
4.91 + g_free(ld->user_friendly);
4.92 + g_free(ld->database_uri);
4.93 + g_free(ld);
4.94 + }
4.95 +}
4.96 +
4.97 +static void plover_local_distributions_finalize(GObject *obj)
4.98 +{
4.99 + PloverLocalDistributionsPrivate *priv;
4.100 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj);
4.101 + g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free,
4.102 + NULL);
4.103 + g_list_free(priv->distributions);
4.104 + if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize)
4.105 + G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj);
4.106 +}
4.107 +
4.108 +static void
4.109 + plover_local_distributions_class_init(PloverLocalDistributionsClass *klass)
4.110 +{
4.111 + GObjectClass *oclass=G_OBJECT_CLASS(klass);
4.112 + oclass->finalize=plover_local_distributions_finalize;
4.113 + g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate));
4.114 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING;
4.115 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING;
4.116 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING;
4.117 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING;
4.118 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING;
4.119 +}
4.120 +
4.121 +static GtkTreeModelFlags
4.122 +plover_local_distributions_get_flags(GtkTreeModel *tree_model)
4.123 +{
4.124 + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
4.125 +}
4.126 +
4.127 +static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model)
4.128 +{
4.129 + return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS;
4.130 +}
4.131 +
4.132 +static GType
4.133 + plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx)
4.134 +{
4.135 + g_return_val_if_fail(indx>=0 && indx<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS,
4.136 + G_TYPE_INVALID);
4.137 + return column_types[indx];
4.138 +}
4.139 +
4.140 +static gboolean plover_local_distributions_get_iter(GtkTreeModel *tree_model,
4.141 + GtkTreeIter *iter,GtkTreePath *path)
4.142 +{
4.143 + int i;
4.144 + PloverLocalDistributionsPrivate *priv;
4.145 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
4.146 + PloverLocalDistribution *ld;
4.147 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
4.148 + i=gtk_tree_path_get_indices(path)[0];
4.149 + ld=g_list_nth_data(priv->distributions,i);
4.150 + if (!ld)
4.151 + return FALSE;
4.152 + iter->stamp=priv->stamp;
4.153 + iter->user_data=ld;
4.154 + return TRUE;
4.155 +}
4.156 +
4.157 +static GtkTreePath *
4.158 + plover_local_distributions_get_path(GtkTreeModel *tree_model,
4.159 + GtkTreeIter *iter)
4.160 +{
4.161 + GtkTreePath *path;
4.162 + PloverLocalDistributionsPrivate *priv;
4.163 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
4.164 + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
4.165 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
4.166 + path=gtk_tree_path_new();
4.167 + gtk_tree_path_append_index(path,
4.168 + g_list_index(priv->distributions,iter->user_data));
4.169 + return path;
4.170 +}
4.171 +
4.172 +static void plover_local_distributions_get_value(GtkTreeModel *tree_model,
4.173 + GtkTreeIter *iter,gint column,GValue *value)
4.174 +{
4.175 + gchar *s;
4.176 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
4.177 + PloverLocalDistribution *ld;
4.178 + g_return_if_fail(column>=0 && column<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS);
4.179 + g_return_if_fail(VALID_ITER(iter,local));
4.180 + ld=iter->user_data;
4.181 + g_value_init(value,column_types[column]);
4.182 + switch((PloverLocalDistributionsColumn)column)
4.183 + {
4.184 + case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN:
4.185 + g_value_set_string(value,ld->vendor);
4.186 + break;
4.187 + case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN:
4.188 + g_value_set_string(value,ld->distribution);
4.189 + break;
4.190 + case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN:
4.191 + g_value_set_string(value,ld->prefix);
4.192 + break;
4.193 + case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN:
4.194 + g_value_set_string(value,ld->user_friendly);
4.195 + break;
4.196 + case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN:
4.197 + g_value_set_string(value,ld->database_uri);
4.198 + break;
4.199 + case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS:
4.200 + /* Quieten compiler warning */
4.201 + break;
4.202 + }
4.203 +}
4.204 +
4.205 +static gboolean
4.206 + plover_local_distributions_iter_next(GtkTreeModel *tree_model,
4.207 + GtkTreeIter *iter)
4.208 +{
4.209 + GList *lnk;
4.210 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
4.211 + PloverLocalDistributionsPrivate *priv;
4.212 + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
4.213 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
4.214 + lnk=g_list_find(priv->distributions,iter->user_data);
4.215 + iter->user_data=lnk->next?lnk->next->data:NULL;
4.216 + return !!iter->user_data;
4.217 +}
4.218 +
4.219 +static gboolean
4.220 + plover_local_distributions_iter_children(GtkTreeModel *tree_model,
4.221 + GtkTreeIter *iter,GtkTreeIter *parent)
4.222 +{
4.223 + PloverLocalDistributionsPrivate *priv;
4.224 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
4.225 + /* this is a list, nodes have no children */
4.226 + if (parent)
4.227 + return FALSE;
4.228 + if (priv->distributions)
4.229 + {
4.230 + iter->stamp=priv->stamp;
4.231 + iter->user_data=priv->distributions->data;
4.232 + return TRUE;
4.233 + }
4.234 + else
4.235 + return FALSE;
4.236 +}
4.237 +
4.238 +static gboolean
4.239 + plover_local_distributions_iter_has_child(GtkTreeModel *tree_model,
4.240 + GtkTreeIter *iter)
4.241 +{
4.242 + PloverLocalDistributionsPrivate *priv;
4.243 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
4.244 + return !!priv->distributions;
4.245 +}
4.246 +
4.247 +static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model,
4.248 + GtkTreeIter *iter)
4.249 +{
4.250 + PloverLocalDistributionsPrivate *priv;
4.251 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
4.252 + if (!iter)
4.253 + return g_list_length(priv->distributions);
4.254 + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
4.255 + return 0;
4.256 +}
4.257 +
4.258 +static gboolean
4.259 + plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model,
4.260 + GtkTreeIter *iter,GtkTreeIter *parent,gint n)
4.261 +{
4.262 + GList *lnk;
4.263 + PloverLocalDistributionsPrivate *priv;
4.264 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
4.265 + if (parent)
4.266 + return FALSE;
4.267 + lnk=g_list_nth(priv->distributions,n);
4.268 + if (!lnk)
4.269 + return FALSE;
4.270 + iter->stamp=priv->stamp;
4.271 + iter->user_data=lnk->data;
4.272 + return TRUE;
4.273 +}
4.274 +
4.275 +static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model,
4.276 + GtkTreeIter *iter,GtkTreeIter *child)
4.277 +{
4.278 + return FALSE;
4.279 +}
4.280 +
4.281 +static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface)
4.282 +{
4.283 + iface->get_flags=plover_local_distributions_get_flags;
4.284 + iface->get_n_columns=plover_local_distributions_get_n_columns;
4.285 + iface->get_column_type=plover_local_distributions_get_column_type;
4.286 + iface->get_iter=plover_local_distributions_get_iter;
4.287 + iface->get_path=plover_local_distributions_get_path;
4.288 + iface->get_value=plover_local_distributions_get_value;
4.289 + iface->iter_next=plover_local_distributions_iter_next;
4.290 + iface->iter_children=plover_local_distributions_iter_children;
4.291 + iface->iter_has_child=plover_local_distributions_iter_has_child;
4.292 + iface->iter_n_children=plover_local_distributions_iter_n_children;
4.293 + iface->iter_nth_child=plover_local_distributions_iter_nth_child;
4.294 + iface->iter_parent=plover_local_distributions_iter_parent;
4.295 +}
4.296 +
4.297 +static void plover_local_distributions_init(PloverLocalDistributions *store)
4.298 +{
4.299 + gchar *s;
4.300 + const char *vendor_prefix,*vendor,*distribution;
4.301 + GDir *vendor_dir,*distribution_dir,*database_dir;
4.302 + PloverLocalDistributionsPrivate *priv;
4.303 + PloverLocalDistribution *ld;
4.304 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store);
4.305 + /*
4.306 + * local distribution databases may be found in
4.307 + * <vendor-prefix>/$VENDOR/$DISTRIBUTION/var/lib/razor and
4.308 + * <vendor-prefix>/$VENDOR/var/lib/razor
4.309 + */
4.310 + vendor_prefix=plover_get_vendor_prefix();
4.311 + g_message("Vendor prefix is %s",vendor_prefix);
4.312 + vendor_dir=g_dir_open(vendor_prefix,0,NULL);
4.313 + if (!vendor_dir)
4.314 + {
4.315 + g_warning("Failed to open %s",vendor_prefix);
4.316 + return;
4.317 + }
4.318 + while((vendor=g_dir_read_name(vendor_dir)))
4.319 + {
4.320 + g_message("Candidate for vendor is %s",vendor);
4.321 + s=g_build_filename(vendor_prefix,vendor,NULL);
4.322 + distribution_dir=g_dir_open(s,0,NULL);
4.323 + g_free(s);
4.324 + if (!distribution_dir)
4.325 + {
4.326 + g_warning("Failed to open %s/%s",vendor_prefix,vendor);
4.327 + continue;
4.328 + }
4.329 + while((distribution=g_dir_read_name(distribution_dir)))
4.330 + {
4.331 + g_message("Candidate for distribution is %s",distribution);
4.332 + if (!strcmp(distribution,"var"))
4.333 + {
4.334 + s=g_build_filename(vendor_prefix,vendor,"var","lib","razor",
4.335 + NULL);
4.336 + database_dir=g_dir_open(s,0,NULL);
4.337 + g_free(s);
4.338 + if (database_dir)
4.339 + {
4.340 + ld=plover_local_distribution_new(vendor,NULL);
4.341 + g_message("Found vendor-specific razor database at %s",
4.342 + ld->database_uri);
4.343 + priv->distributions=g_list_prepend(priv->distributions,ld);
4.344 + g_dir_close(database_dir);
4.345 + }
4.346 + else
4.347 + g_warning("Failed to open %s/%s/var/lib/razor",
4.348 + vendor_prefix,vendor);
4.349 + }
4.350 + s=g_build_filename(vendor_prefix,vendor,distribution,
4.351 + "var","lib","razor",NULL);
4.352 + database_dir=g_dir_open(s,0,NULL);
4.353 + g_free(s);
4.354 + if (database_dir)
4.355 + {
4.356 + ld=plover_local_distribution_new(vendor,distribution);
4.357 + g_message("Found local-distribution razor database at %s",
4.358 + ld->database_uri);
4.359 + priv->distributions=g_list_prepend(priv->distributions,ld);
4.360 + g_dir_close(database_dir);
4.361 + }
4.362 + else
4.363 + g_warning("Failed to open %s/%s/%s/var/lib/razor",
4.364 + vendor_prefix,vendor,distribution);
4.365 + }
4.366 + g_dir_close(distribution_dir);
4.367 + }
4.368 + g_dir_close(vendor_dir);
4.369 + priv->stamp=g_random_int();
4.370 +}
4.371 +
4.372 +PloverLocalDistributions *plover_local_distributions_new(void)
4.373 +{
4.374 + return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL);
4.375 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/app-manager/localdistributions.h Tue Apr 25 17:41:00 2023 +0100
5.3 @@ -0,0 +1,52 @@
5.4 +#ifndef __PLOVER_LOCAL_DISTRIBUTIONS_H__
5.5 +#define __PLOVER_LOCAL_DISTRIBUTIONS_H__
5.6 +
5.7 +#include <glib-object.h>
5.8 +
5.9 +G_BEGIN_DECLS
5.10 +
5.11 +#define PLOVER_TYPE_LOCAL_DISTRIBUTIONS\
5.12 + plover_local_distributions_get_type()
5.13 +#define PLOVER_LOCAL_DISTRIBUTIONS(obj)\
5.14 + G_TYPE_CHECK_INSTANCE_CAST(obj,\
5.15 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
5.16 + PloverLocalDistributions)
5.17 +#define PLOVER_LOCAL_DISTRIBUTIONS_CLASS(klass)\
5.18 + G_TYPE_CHECK_CLASS_CAST(klass,\
5.19 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
5.20 + PloverLocalDistributionsClass)
5.21 +#define PLOVER_IS_LOCAL_DISTRIBUTIONS(obj)\
5.22 + G_TYPE_CHECK_INSTANCE_TYPE(obj,\
5.23 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS)
5.24 +#define PLOVER_IS_LOCAL_DISTRIBUTIONS_CLASS(klass)\
5.25 + G_TYPE_CHECK_CLASS_TYPE(obj,\
5.26 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS)
5.27 +#define PLOVER_LOCAL_DISTRIBUTIONS_GET_CLASS(obj)\
5.28 + G_TYPE_INSTANCE_GET_CLASS(obj,\
5.29 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
5.30 + PloverLocalDistributionsClass)
5.31 +
5.32 +typedef enum
5.33 +{
5.34 + PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN,
5.35 + PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN,
5.36 + PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN,
5.37 + PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN,
5.38 + PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN,
5.39 + PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS
5.40 +} PloverLocalDistributionsColumn;
5.41 +
5.42 +typedef struct _PloverLocalDistributions {
5.43 + GObject parent_instance;
5.44 +} PloverLocalDistributions;
5.45 +
5.46 +typedef struct _PloverLocalDistributionsClass {
5.47 + GObjectClass parent_class;
5.48 +} PloverLocalDistributionsClass;
5.49 +
5.50 +GType plover_local_distributions_get_type(void) G_GNUC_CONST;
5.51 +PloverLocalDistributions *plover_local_distributions_new(void);
5.52 +
5.53 +G_END_DECLS
5.54 +
5.55 +#endif /* __PLOVER_LOCAL_DISTRIBUTIONS_H__ */
6.1 --- a/app-manager/packagelist.c Tue Jun 29 10:09:34 2021 +0100
6.2 +++ b/app-manager/packagelist.c Tue Apr 25 17:41:00 2023 +0100
6.3 @@ -20,8 +20,10 @@
6.4 #include <stdlib.h>
6.5 #include <string.h>
6.6 #include <gtk/gtk.h>
6.7 +#include <plover/plover.h>
6.8 #include <plover/package.h>
6.9 #include <plover/packageset.h>
6.10 +#include <plover/yumrepository.h>
6.11 #include <plover-gtk/packagestore.h>
6.12 #include <plover-gtk/packagefilestore.h>
6.13 #include "app-manager.h"
6.14 @@ -32,11 +34,18 @@
6.15
6.16 void package_present(PloverPackage *package)
6.17 {
6.18 - gchar *s;
6.19 + gchar *s,*prefix,*prefix_path;
6.20 const char *text,*t;
6.21 + char *multiple_prefixes="multiple";
6.22 + GError *tmp_err=NULL;
6.23 + GSList *sets,*repositories,*lnk;
6.24 GtkWidget *w;
6.25 GtkTextBuffer *buf;
6.26 + GtkTreeModel *model;
6.27 + struct comps *comps;
6.28 + PloverPackageSet *set;
6.29 PloverPackageFileStore *store;
6.30 + PloverRepository *repository;
6.31 buf=GTK_TEXT_BUFFER(gtk_builder_get_object(ui,"description"));
6.32 if (package)
6.33 {
6.34 @@ -44,7 +53,99 @@
6.35 g_strdelimit(s,"\t\n",' ');
6.36 }
6.37 else
6.38 - s=g_strdup("");
6.39 + {
6.40 + model=gtk_tree_view_get_model(view);
6.41 + while(model &&
6.42 + (GTK_IS_TREE_MODEL_FILTER(model) || GTK_IS_TREE_MODEL_SORT(model)))
6.43 + {
6.44 + if (GTK_IS_TREE_MODEL_FILTER(model))
6.45 + model=
6.46 + gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model));
6.47 + else
6.48 + model=gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));
6.49 + }
6.50 + repositories=NULL;
6.51 + prefix=NULL;
6.52 + if (model && PLOVER_IS_PACKAGE_STORE(model))
6.53 + {
6.54 + sets=plover_package_store_get_sets(PLOVER_PACKAGE_STORE(model));
6.55 + for(lnk=sets;lnk;lnk=lnk->next)
6.56 + {
6.57 + set=lnk->data;
6.58 + repository=plover_package_set_get_repository(set);
6.59 + if (repository && !g_slist_find(repositories,repository))
6.60 + repositories=g_slist_prepend(repositories,repository);
6.61 + t=plover_package_set_guess_prefix(set,tmp_err?NULL:&tmp_err);
6.62 + if (!t)
6.63 + continue;
6.64 + if (!prefix)
6.65 + prefix=g_strdup(t);
6.66 + else if (prefix!=multiple_prefixes && strcmp(prefix,t))
6.67 + {
6.68 + g_free(prefix);
6.69 + prefix=multiple_prefixes;
6.70 + }
6.71 + }
6.72 + if (prefix==multiple_prefixes)
6.73 + s=g_strdup("Multiple install prefixes");
6.74 + else if (repositories)
6.75 + {
6.76 + if (prefix!=multiple_prefixes)
6.77 + g_free(prefix);
6.78 + prefix=NULL;
6.79 + for(lnk=repositories;lnk;lnk=lnk->next)
6.80 + {
6.81 + repository=lnk->data;
6.82 + if (PLOVER_IS_YUM_REPOSITORY(repository))
6.83 + {
6.84 + comps=plover_yum_repository_get_comps(
6.85 + PLOVER_YUM_REPOSITORY(repository),NULL);
6.86 + t=plover_comps_get_default_prefix(comps);
6.87 + if (!prefix)
6.88 + prefix=g_strdup(t);
6.89 + else if (prefix!=multiple_prefixes && strcmp(prefix,t))
6.90 + {
6.91 + g_free(prefix);
6.92 + prefix=multiple_prefixes;
6.93 + }
6.94 + }
6.95 + }
6.96 + if (prefix==multiple_prefixes)
6.97 + s=g_strdup("Repositories intended to be installed to "
6.98 + "multiple destinations");
6.99 + else if (prefix)
6.100 + {
6.101 + prefix_path=razor_path_from_uri(prefix,NULL);
6.102 + s=g_strdup_printf("Repository intended to be installed to: "
6.103 + "%s",prefix_path?prefix_path:prefix);
6.104 + g_free(prefix_path);
6.105 + }
6.106 + else
6.107 + s=g_strdup("Repository with no default "
6.108 + "install destination");
6.109 + }
6.110 + else if (prefix)
6.111 + {
6.112 + prefix_path=razor_path_from_uri(prefix,NULL);
6.113 + s=g_strdup_printf("Installed in: %s",
6.114 + prefix_path?prefix_path:prefix);
6.115 + g_free(prefix_path);
6.116 + }
6.117 + else if (sets)
6.118 + s=g_strdup("No common installation destination found");
6.119 + else
6.120 + s=g_strdup("Empty package store");
6.121 + if (prefix!=multiple_prefixes)
6.122 + g_free(prefix);
6.123 + g_slist_free(repositories);
6.124 + g_clear_error(&tmp_err);
6.125 + }
6.126 + else if (model)
6.127 + s=g_strdup_printf("Unsupported package list container (%s)",
6.128 + G_OBJECT_TYPE_NAME(model));
6.129 + else
6.130 + s=g_strdup("No Package list container");
6.131 + }
6.132 gtk_text_buffer_set_text(buf,s,-1);
6.133 g_free(s);
6.134 w=GTK_WIDGET(gtk_builder_get_object(ui,"PackageDetails"));
6.135 @@ -149,6 +250,33 @@
6.136 }
6.137 }
6.138
6.139 +static void package_inserted(GtkTreeModel *tree_model,GtkTreePath *path,
6.140 + GtkTreeIter *iter,gpointer data)
6.141 +{
6.142 + gchar *s;
6.143 + s=gtk_tree_path_to_string(path);
6.144 + g_message("package_inserted(%s): %sactive package",
6.145 + s,active?"":"no ");
6.146 + g_free(s);
6.147 + if (!active)
6.148 + package_present(NULL);
6.149 +}
6.150 +
6.151 +static void package_deleted(GtkTreeModel *tree_model,GtkTreePath *path,
6.152 + gpointer data)
6.153 +{
6.154 + /*
6.155 + * If the deleted package was the active one, then selection-changed
6.156 + * will be emitted which will handle that case.
6.157 + */
6.158 + gchar *s;
6.159 + s=gtk_tree_path_to_string(path);
6.160 + g_message("package_deleted(%s): %sactive package",s,active?"":"no ");
6.161 + g_free(s);
6.162 + if (!active)
6.163 + package_present(NULL);
6.164 +}
6.165 +
6.166 static void package_cell_data_func(GtkTreeViewColumn *column,
6.167 GtkCellRenderer *cell,GtkTreeModel *model,GtkTreeIter *iter,gpointer data)
6.168 {
6.169 @@ -169,9 +297,21 @@
6.170 void set_package_model(GtkTreeModel *model)
6.171 {
6.172 GtkWidget *w;
6.173 + GtkTreeModel *old_model;
6.174 GtkTreeViewColumn *column;
6.175 GtkCellRenderer *renderer;
6.176 GtkTreeSelection *selection;
6.177 + if (view)
6.178 + {
6.179 + old_model=gtk_tree_view_get_model(view);
6.180 + if (old_model)
6.181 + {
6.182 + g_signal_handlers_disconnect_by_func(old_model,
6.183 + G_CALLBACK(package_inserted),NULL);
6.184 + g_signal_handlers_disconnect_by_func(old_model,
6.185 + G_CALLBACK(package_deleted),NULL);
6.186 + }
6.187 + }
6.188 if (!view)
6.189 {
6.190 w=GTK_WIDGET(gtk_builder_get_object(ui,"Packages"));
6.191 @@ -218,9 +358,18 @@
6.192 }
6.193 if (view)
6.194 {
6.195 + g_warning("set_package_model: Calling gtk_tree_view_set_model()");
6.196 gtk_tree_view_set_model(view,model);
6.197 + g_warning("set_package_model: gtk_tree_view_set_model() returns");
6.198 gtk_tree_view_set_search_column(view,
6.199 PLOVER_PACKAGE_STORE_NAME_COLUMN);
6.200 + if (model)
6.201 + {
6.202 + g_signal_connect(model,"row-inserted",G_CALLBACK(package_inserted),
6.203 + NULL);
6.204 + g_signal_connect(model,"row-deleted",G_CALLBACK(package_deleted),
6.205 + NULL);
6.206 + }
6.207 }
6.208 package_present(NULL);
6.209 }
7.1 --- a/app-manager/resources.rc.in Tue Jun 29 10:09:34 2021 +0100
7.2 +++ b/app-manager/resources.rc.in Tue Apr 25 17:41:00 2023 +0100
7.3 @@ -22,7 +22,7 @@
7.4 VALUE "FileVersion","@PACKAGE_VERSION@"
7.5 VALUE "InternalName","app-manager"
7.6 VALUE "LegalCopyright",
7.7 - "Copyright © 2010 J. Ali Harlow et al"
7.8 + "Copyright © 2010, 2023 J. Ali Harlow et al"
7.9 VALUE "OriginalFilename","app-manager.exe"
7.10 VALUE "ProductName","plover"
7.11 VALUE "ProductVersion","@PACKAGE_VERSION@"
8.1 --- a/configure.ac Tue Jun 29 10:09:34 2021 +0100
8.2 +++ b/configure.ac Tue Apr 25 17:41:00 2023 +0100
8.3 @@ -65,9 +65,9 @@
8.4 # increment CURRENT and set AGE and REVISION to 0.
8.5 # - If the interface is the same as the previous version, increment REVISION.
8.6 #
8.7 -lt_current=5
8.8 +lt_current=6
8.9 lt_revision=0
8.10 -lt_age=2
8.11 +lt_age=3
8.12 LIBPLOVER_LT_VERSION_INFO="$lt_current:$lt_revision:$lt_age"
8.13 AC_SUBST(LIBPLOVER_LT_VERSION_INFO)
8.14
8.15 @@ -142,8 +142,10 @@
8.16 PKG_CHECK_MODULES(GMODULE_EXPORT,[gmodule-export-2.0])
8.17 LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS $GIO_CFLAGS"
8.18 LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS $GIO_LIBS"
8.19 +LIBPLOVER_REQUIREMENTS="razor expat zlib glib2"
8.20 AC_SUBST(LIBPLOVER_CFLAGS)
8.21 AC_SUBST(LIBPLOVER_LIBS)
8.22 +AC_SUBST(LIBPLOVER_REQUIREMENTS)
8.23 PLOVER_GTK_CFLAGS="$GTK_CFLAGS $RAZOR_CFLAGS"
8.24 PLOVER_GTK_LIBS="$GTK_LIBS $RAZOR_LIBS"
8.25 AC_SUBST(PLOVER_GTK_CFLAGS)
8.26 @@ -155,12 +157,6 @@
8.27 LIBS="$save_LIBS"
8.28 AC_SUBST(LUA_POSIX_CFLAGS)
8.29 AC_SUBST(LUA_POSIX_LIBS)
8.30 -GUI_CFLAGS="$GMODULE_EXPORT_CFLAGS $WHELK_CFLAGS $PLOVER_GTK_CFLAGS \
8.31 - $LIBPLOVER_CFLAGS $LUA_POSIX_CFLAGS"
8.32 -GUI_LIBS="$GMODULE_EXPORT_LIBS $WHELK_LIBS $PLOVER_GTK_LIBS \
8.33 - $LIBPLOVER_LIBS $LUA_POSIX_LIBS"
8.34 -AC_SUBST(GUI_CFLAGS)
8.35 -AC_SUBST(GUI_LIBS)
8.36 save_PKG_CONFIG="$PKG_CONFIG"
8.37 PKG_CONFIG="$PKG_CONFIG --static"
8.38 PKG_CHECK_MODULES(SETUP,[whelk razor >= 0.5.4 expat >= 2.2 zlib gio-2.0],[:],
8.39 @@ -201,13 +197,28 @@
8.40 [have_breakpad="yes";REQUIREMENTS="$REQUIREMENTS x11"],[have_breakpad="no"])
8.41 if test "$have_breakpad" = yes; then
8.42 AC_DEFINE([HAVE_BREAKPAD],[1],[Define if breakpad is available.])
8.43 + LIBPLOVER_PRIVATE_REQUIREMENTS="breakpad-client"
8.44 + # breakpad-client uses C++. This should probably go into
8.45 + # Libs.private in breakpad-client.pc
8.46 + AS_IF([test -n "$host_mingw"],[
8.47 + static_stdcxx=`$CXX --print-file-name=libstdc++.a`
8.48 + LIBPLOVER_PRIVATE_LIBS="-lversion -lgcc_eh $static_stdcxx"
8.49 + ])
8.50 elif test "$with_breakpad" = yes; then
8.51 AC_MSG_ERROR([$BREAKPAD_PKG_ERRORS])
8.52 fi
8.53 else
8.54 have_breakpad="no"
8.55 fi
8.56 +AC_SUBST(LIBPLOVER_PRIVATE_REQUIREMENTS)
8.57 +AC_SUBST(LIBPLOVER_PRIVATE_LIBS)
8.58 AM_CONDITIONAL([HAVE_BREAKPAD],[test $have_breakpad = yes])
8.59 +GUI_CFLAGS="$GMODULE_EXPORT_CFLAGS $WHELK_CFLAGS $PLOVER_GTK_CFLAGS \
8.60 + $LIBPLOVER_CFLAGS $LUA_POSIX_CFLAGS"
8.61 +GUI_LIBS="$GMODULE_EXPORT_LIBS $WHELK_LIBS $PLOVER_GTK_LIBS \
8.62 + $LIBPLOVER_LIBS $LIBPLOVER_PRIVATE_LIBS $LUA_POSIX_LIBS"
8.63 +AC_SUBST(GUI_CFLAGS)
8.64 +AC_SUBST(GUI_LIBS)
8.65
8.66 ##################################################
8.67 # Checks for library functions.
9.1 --- a/plover-gtk/packagestore.c Tue Jun 29 10:09:34 2021 +0100
9.2 +++ b/plover-gtk/packagestore.c Tue Apr 25 17:41:00 2023 +0100
9.3 @@ -298,35 +298,64 @@
9.4 return strcmp(plover_package_get_name(pa),plover_package_get_name(pb));
9.5 }
9.6
9.7 +static gint
9.8 + plover__sequence_iter_compar(gconstpointer a,gconstpointer b)
9.9 +{
9.10 + GSequenceIter *sia=(GSequenceIter *)a;
9.11 + GSequenceIter *sib=(GSequenceIter *)b;
9.12 + return g_sequence_iter_get_position(sia)-g_sequence_iter_get_position(sib);
9.13 +}
9.14 +
9.15 void plover_package_store_add_set(PloverPackageStore *store,
9.16 PloverPackageSet *set)
9.17 {
9.18 - GSList *packages,*link;
9.19 + GSList *packages,*lnk;
9.20 GSequenceIter *si;
9.21 GtkTreeIter ti;
9.22 GtkTreePath *path;
9.23 - gint *indices;
9.24 PloverPackageStorePrivate *priv;
9.25 g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
9.26 g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
9.27 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
9.28 g_return_if_fail(g_slist_find(priv->sets,set) == NULL);
9.29 g_object_ref(set);
9.30 + /*
9.31 + * This is a little complicated because we don't want to
9.32 + * emit row-inserted until we have actually added set to
9.33 + * the list of sets. On the other hand, we don't want to
9.34 + * add set to the list of sets until all the packages it
9.35 + * contains have been added to the sequence.
9.36 + * Thus, this two phase implementation.
9.37 + * However, this introduces an addition complication in
9.38 + * that the original row numbers are no longer valid as
9.39 + * we keep inserting rows. GSequenceIter should deal with
9.40 + * this, but it seems to be giving us problems. Just go
9.41 + * with the simple solution.
9.42 + * Finally, the positions of the result have to be
9.43 + * published in increasing order to avoid confusing
9.44 + * subscribers.
9.45 + */
9.46 + packages=plover_package_set_get_packages(set);
9.47 + for(lnk=packages;lnk;lnk=lnk->next)
9.48 + g_sequence_insert_sorted(priv->seq,lnk->data,
9.49 + plover__package_compar,NULL);
9.50 + priv->sets=g_slist_prepend(priv->sets,set);
9.51 + priv->stamp++;
9.52 path=gtk_tree_path_new();
9.53 gtk_tree_path_append_index(path,0);
9.54 - indices=gtk_tree_path_get_indices(path);
9.55 - packages=plover_package_set_get_packages(set);
9.56 - for(link=packages;link;link=link->next)
9.57 + si=g_sequence_get_begin_iter(priv->seq);
9.58 + while(!g_sequence_iter_is_end(si))
9.59 {
9.60 - si=g_sequence_insert_sorted(priv->seq,link->data,
9.61 - plover__package_compar,NULL);
9.62 - *indices=g_sequence_iter_get_position(si);
9.63 - ti.stamp=priv->stamp;
9.64 - ti.user_data=si;
9.65 - gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
9.66 + if (g_slist_find(packages,g_sequence_get(si)))
9.67 + {
9.68 + ti.stamp=priv->stamp;
9.69 + ti.user_data=si;
9.70 + gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
9.71 + }
9.72 + si=g_sequence_iter_next(si);
9.73 + gtk_tree_path_next(path);
9.74 }
9.75 gtk_tree_path_free(path);
9.76 - priv->sets=g_slist_prepend(priv->sets,set);
9.77 }
9.78
9.79 void plover_package_store_remove_set(PloverPackageStore *store,
10.1 --- a/plover/Makefile.am Tue Jun 29 10:09:34 2021 +0100
10.2 +++ b/plover/Makefile.am Tue Apr 25 17:41:00 2023 +0100
10.3 @@ -1,18 +1,18 @@
10.4 -AM_CFLAGS=-g $(LIBPLOVER_CFLAGS) $(CODE_COVERAGE_CFLAGS)
10.5 -AM_CXXFLAGS=-g $(LIBPLOVER_CFLAGS) $(CODE_COVERAGE_CFLAGS)
10.6 -LIBS=$(LIBPLOVER_LIBS)
10.7 +AM_CFLAGS=-g $(LIBPLOVER_CFLAGS) $(CODE_COVERAGE_CFLAGS) $(BREAKPAD_CFLAGS)
10.8 +AM_CXXFLAGS=-g $(LIBPLOVER_CFLAGS) $(CODE_COVERAGE_CFLAGS) $(BREAKPAD_CFLAGS)
10.9 +LIBS=$(LIBPLOVER_LIBS) $(BREAKPAD_LIBS)
10.10 INCLUDES=-I$(top_srcdir)
10.11 AM_LDFLAGS=-no-undefined -version-info $(LIBPLOVER_LT_VERSION_INFO) \
10.12 $(CODE_COVERAGE_LDFLAGS) -export-symbols-regex '^plover_[^_]'
10.13
10.14 pkginclude_HEADERS=plover.h transaction.h package.h packageset.h repository.h \
10.15 - inputstream.h
10.16 + yumrepository.h inputstream.h
10.17
10.18 lib_LTLIBRARIES=libplover.la
10.19 libplover_la_SOURCES=$(pkginclude_HEADERS) util.c import-yum.c razor.c comps.c \
10.20 log.c vector.c transaction.c package.c packageset.c repository.c \
10.21 - uri-handler.c uri-handler.h inputstream.c exception-handler.cpp \
10.22 - ascii-ctype.h
10.23 + yumrepository.c uri-handler.c uri-handler.h inputstream.c \
10.24 + exception-handler.cpp ascii-ctype.h
10.25
10.26 pkgconfigdir=$(libdir)/pkgconfig
10.27 pkgconfig_DATA=plover.pc
11.1 --- a/plover/exception-handler.cpp Tue Jun 29 10:09:34 2021 +0100
11.2 +++ b/plover/exception-handler.cpp Tue Apr 25 17:41:00 2023 +0100
11.3 @@ -17,6 +17,7 @@
11.4 */
11.5
11.6 #include <cstdlib>
11.7 +#include "config.h"
11.8 #include "plover/plover.h"
11.9 #if defined(HAVE_BREAKPAD) && defined(WIN32)
11.10 #include <breakpad/client/windows/crash_generation/crash_generation_client.h>
11.11 @@ -42,7 +43,7 @@
11.12 plover_exception_handler=new
11.13 google_breakpad::ExceptionHandler(dump_path,NULL,NULL,NULL,
11.14 google_breakpad::ExceptionHandler::HANDLER_ALL,MiniDumpWithDataSegs,
11.15 - NULL,NULL);
11.16 + (WCHAR *)NULL,NULL);
11.17 g_free(dump_path);
11.18 }
11.19 #endif /* HAVE_BREAKPAD && WIN32 */
12.1 --- a/plover/import-yum.c Tue Jun 29 10:09:34 2021 +0100
12.2 +++ b/plover/import-yum.c Tue Apr 25 17:41:00 2023 +0100
12.3 @@ -18,454 +18,25 @@
12.4 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
12.5 */
12.6
12.7 -#define _GNU_SOURCE
12.8 -
12.9 -#include <string.h>
12.10 -#include <stdio.h>
12.11 -#include <stdint.h>
12.12 -#include <sys/stat.h>
12.13 -#include <unistd.h>
12.14 -#include <fcntl.h>
12.15 -#include <errno.h>
12.16 -
12.17 #include <glib.h>
12.18 -#include <expat.h>
12.19 -#include <zlib.h>
12.20 #include <razor.h>
12.21 -#include "plover/plover.h"
12.22 -#include "plover/uri-handler.h"
12.23 -#include "plover/inputstream.h"
12.24 +#include <plover/plover.h>
12.25 +#include <plover/uri-handler.h>
12.26 +#include "plover/yumrepository.h"
12.27
12.28 /* Import a yum filelist as a razor package set. */
12.29
12.30 -enum {
12.31 - YUM_STATE_BEGIN,
12.32 - YUM_STATE_PACKAGE_NAME,
12.33 - YUM_STATE_PACKAGE_ARCH,
12.34 - YUM_STATE_SUMMARY,
12.35 - YUM_STATE_DESCRIPTION,
12.36 - YUM_STATE_URL,
12.37 - YUM_STATE_LICENSE,
12.38 - YUM_STATE_CHECKSUM,
12.39 - YUM_STATE_REQUIRES,
12.40 - YUM_STATE_PROVIDES,
12.41 - YUM_STATE_OBSOLETES,
12.42 - YUM_STATE_CONFLICTS,
12.43 - YUM_STATE_SKIPPING_PACKAGE,
12.44 - YUM_STATE_FILE
12.45 -};
12.46 -
12.47 -struct yum_context {
12.48 - XML_Parser primary_parser;
12.49 - XML_Parser filelists_parser;
12.50 - XML_Parser current_parser;
12.51 -
12.52 - struct razor_importer *importer;
12.53 - struct import_property_context *current_property_context;
12.54 - const char *base_uri;
12.55 - GTree *uris;
12.56 - char name[256], arch[64], summary[512], description[4096];
12.57 - char url[256], license[64], buffer[512], *p;
12.58 - char pkgid[128], evr[128];
12.59 - uint32_t property_type;
12.60 - int state;
12.61 -
12.62 - int total, current;
12.63 -};
12.64 -
12.65 -static uint32_t
12.66 -yum_to_razor_relation (const char *flags)
12.67 -{
12.68 - if (flags[0] == 'L') {
12.69 - if (flags[1] == 'T')
12.70 - return RAZOR_PROPERTY_LESS;
12.71 - else
12.72 - return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
12.73 - } else if (flags[0] == 'G') {
12.74 - if (flags[1] == 'T')
12.75 - return RAZOR_PROPERTY_GREATER;
12.76 - else
12.77 - return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
12.78 - } else
12.79 - return RAZOR_PROPERTY_EQUAL;
12.80 -}
12.81 -
12.82 -static void
12.83 -yum_primary_start_element(void *data, const char *name, const char **atts)
12.84 -{
12.85 - struct yum_context *ctx = data;
12.86 - const char *n, *epoch, *version, *release;
12.87 - char buffer[128];
12.88 - char *s;
12.89 - gchar *nevra;
12.90 - uint32_t pre, relation, flags;
12.91 - int i;
12.92 -
12.93 - if (ctx->state == YUM_STATE_SKIPPING_PACKAGE)
12.94 - return;
12.95 -
12.96 - if (strcmp(name, "metadata") == 0) {
12.97 - for (i = 0; atts[i]; i += 2) {
12.98 - if (strcmp(atts[i], "packages") == 0)
12.99 - ctx->total = atoi(atts[i + 1]);
12.100 - }
12.101 - } else if (strcmp(name, "package") == 0) {
12.102 - *ctx->name=*ctx->arch=*ctx->summary=*ctx->description='\0';
12.103 - *ctx->url=*ctx->license='\0';
12.104 - } else if (strcmp(name, "name") == 0) {
12.105 - ctx->state = YUM_STATE_PACKAGE_NAME;
12.106 - ctx->p = ctx->name;
12.107 - } else if (strcmp(name, "arch") == 0) {
12.108 - ctx->state = YUM_STATE_PACKAGE_ARCH;
12.109 - ctx->p = ctx->arch;
12.110 - } else if (strcmp(name, "version") == 0) {
12.111 - epoch = NULL;
12.112 - version = NULL;
12.113 - release = NULL;
12.114 - for (i = 0; atts[i]; i += 2) {
12.115 - if (strcmp(atts[i], "epoch") == 0)
12.116 - epoch = atts[i + 1];
12.117 - else if (strcmp(atts[i], "ver") == 0)
12.118 - version = atts[i + 1];
12.119 - else if (strcmp(atts[i], "rel") == 0)
12.120 - release = atts[i + 1];
12.121 - }
12.122 - if (version == NULL || release == NULL) {
12.123 - fprintf(stderr, "invalid version tag, "
12.124 - "missing version or release attribute\n");
12.125 - return;
12.126 - }
12.127 -
12.128 - razor_build_evr(ctx->evr, sizeof ctx->evr, epoch, version,
12.129 - release);
12.130 - if (!strcmp(ctx->arch, "noarch") ||
12.131 - !strcmp(ctx->arch, razor_system_arch())) {
12.132 - razor_importer_begin_package(ctx->importer, ctx->name,
12.133 - ctx->evr, ctx->arch);
12.134 - } else
12.135 - ctx->state = YUM_STATE_SKIPPING_PACKAGE;
12.136 - } else if (strcmp(name, "summary") == 0) {
12.137 - ctx->p = ctx->summary;
12.138 - ctx->state = YUM_STATE_SUMMARY;
12.139 - } else if (strcmp(name, "description") == 0) {
12.140 - ctx->p = ctx->description;
12.141 - ctx->state = YUM_STATE_DESCRIPTION;
12.142 - } else if (strcmp(name, "url") == 0) {
12.143 - ctx->p = ctx->url;
12.144 - ctx->state = YUM_STATE_URL;
12.145 - } else if (strcmp(name, "checksum") == 0) {
12.146 - ctx->p = ctx->pkgid;
12.147 - ctx->state = YUM_STATE_CHECKSUM;
12.148 - } else if (strcmp(name, "location") == 0) {
12.149 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
12.150 - for (i = 0; atts[i]; i += 2)
12.151 - if (strcmp(atts[i], "href") == 0) {
12.152 - nevra=g_strconcat(ctx->name,"-",ctx->evr,".",
12.153 - ctx->arch,NULL);
12.154 - s=razor_path_relative_to_uri(ctx->base_uri,
12.155 - atts[i + 1],NULL);
12.156 - g_tree_insert(ctx->uris,nevra,g_strdup(s));
12.157 - free(s);
12.158 - break;
12.159 - }
12.160 - }
12.161 - } else if (strcmp(name, "rpm:license") == 0) {
12.162 - ctx->p = ctx->license;
12.163 - ctx->state = YUM_STATE_LICENSE;
12.164 - } else if (strcmp(name, "rpm:requires") == 0) {
12.165 - ctx->state = YUM_STATE_REQUIRES;
12.166 - ctx->property_type = RAZOR_PROPERTY_REQUIRES;
12.167 - } else if (strcmp(name, "rpm:provides") == 0) {
12.168 - ctx->state = YUM_STATE_PROVIDES;
12.169 - ctx->property_type = RAZOR_PROPERTY_PROVIDES;
12.170 - } else if (strcmp(name, "rpm:obsoletes") == 0) {
12.171 - ctx->state = YUM_STATE_OBSOLETES;
12.172 - ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
12.173 - } else if (strcmp(name, "rpm:conflicts") == 0) {
12.174 - ctx->state = YUM_STATE_CONFLICTS;
12.175 - ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
12.176 - } else if (strcmp(name, "rpm:entry") == 0 &&
12.177 - ctx->state != YUM_STATE_BEGIN) {
12.178 - n = NULL;
12.179 - epoch = NULL;
12.180 - version = NULL;
12.181 - release = NULL;
12.182 - relation = RAZOR_PROPERTY_EQUAL;
12.183 - pre = 0;
12.184 - for (i = 0; atts[i]; i += 2) {
12.185 - if (strcmp(atts[i], "name") == 0)
12.186 - n = atts[i + 1];
12.187 - else if (strcmp(atts[i], "epoch") == 0)
12.188 - epoch = atts[i + 1];
12.189 - else if (strcmp(atts[i], "ver") == 0)
12.190 - version = atts[i + 1];
12.191 - else if (strcmp(atts[i], "rel") == 0)
12.192 - release = atts[i + 1];
12.193 - else if (strcmp(atts[i], "flags") == 0)
12.194 - relation = yum_to_razor_relation(atts[i + 1]);
12.195 - else if (strcmp(atts[i], "pre") == 0)
12.196 - pre = RAZOR_PROPERTY_PRE;
12.197 - }
12.198 -
12.199 - if (n == NULL) {
12.200 - fprintf(stderr, "invalid rpm:entry, "
12.201 - "missing name or version attributes\n");
12.202 - return;
12.203 - }
12.204 -
12.205 - razor_build_evr(buffer, sizeof buffer, epoch, version, release);
12.206 - flags = ctx->property_type | relation | pre;
12.207 - razor_importer_add_property(ctx->importer, n, flags, buffer);
12.208 - }
12.209 -}
12.210 -
12.211 -static void
12.212 -yum_primary_end_element (void *data, const char *name)
12.213 -{
12.214 - struct yum_context *ctx = data;
12.215 -
12.216 - switch (ctx->state) {
12.217 - case YUM_STATE_PACKAGE_NAME:
12.218 - case YUM_STATE_PACKAGE_ARCH:
12.219 - case YUM_STATE_SUMMARY:
12.220 - case YUM_STATE_DESCRIPTION:
12.221 - case YUM_STATE_URL:
12.222 - case YUM_STATE_LICENSE:
12.223 - case YUM_STATE_CHECKSUM:
12.224 - case YUM_STATE_FILE:
12.225 - ctx->state = YUM_STATE_BEGIN;
12.226 - break;
12.227 - }
12.228 -
12.229 - if (strcmp(name, "package") == 0) {
12.230 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
12.231 - razor_importer_add_details(ctx->importer, ctx->summary,
12.232 - ctx->description, ctx->url,
12.233 - ctx->license);
12.234 -
12.235 - XML_StopParser(ctx->current_parser, XML_TRUE);
12.236 - ctx->current_parser = ctx->filelists_parser;
12.237 - }
12.238 -}
12.239 -
12.240 -static void
12.241 -yum_character_data (void *data, const XML_Char *s, int len)
12.242 -{
12.243 - struct yum_context *ctx = data;
12.244 -
12.245 - switch (ctx->state) {
12.246 - case YUM_STATE_PACKAGE_NAME:
12.247 - case YUM_STATE_PACKAGE_ARCH:
12.248 - case YUM_STATE_SUMMARY:
12.249 - case YUM_STATE_DESCRIPTION:
12.250 - case YUM_STATE_URL:
12.251 - case YUM_STATE_LICENSE:
12.252 - case YUM_STATE_CHECKSUM:
12.253 - case YUM_STATE_FILE:
12.254 - memcpy(ctx->p, s, len);
12.255 - ctx->p += len;
12.256 - *ctx->p = '\0';
12.257 - break;
12.258 - }
12.259 -}
12.260 -
12.261 -static void
12.262 -yum_filelists_start_element(void *data, const char *name, const char **atts)
12.263 -{
12.264 - struct yum_context *ctx = data;
12.265 - const char *pkg, *pkgid;
12.266 - int i;
12.267 -
12.268 - if (strcmp(name, "package") == 0 &&
12.269 - ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
12.270 - pkg = NULL;
12.271 - pkgid = NULL;
12.272 - for (i = 0; atts[i]; i += 2) {
12.273 - if (strcmp(atts[i], "name") == 0)
12.274 - pkg = atts[i + 1];
12.275 - else if (strcmp(atts[i], "pkgid") == 0)
12.276 - pkgid = atts[i + 1];
12.277 - }
12.278 - if (strcmp(pkgid, ctx->pkgid) != 0)
12.279 - fprintf(stderr, "primary.xml and filelists.xml "
12.280 - "mismatch for %s: %s vs %s",
12.281 - pkg, pkgid, ctx->pkgid);
12.282 - } else if (strcmp(name, "file") == 0) {
12.283 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
12.284 - ctx->state = YUM_STATE_FILE;
12.285 - ctx->p = ctx->buffer;
12.286 - }
12.287 -}
12.288 -
12.289 -static void
12.290 -yum_filelists_end_element (void *data, const char *name)
12.291 -{
12.292 - struct yum_context *ctx = data;
12.293 -
12.294 - if (strcmp(name, "package") == 0) {
12.295 - XML_StopParser(ctx->current_parser, XML_TRUE);
12.296 - ctx->current_parser = ctx->primary_parser;
12.297 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
12.298 - razor_importer_finish_package(ctx->importer);
12.299 - ctx->state = YUM_STATE_BEGIN;
12.300 - } else if (strcmp(name, "file") == 0) {
12.301 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
12.302 - razor_importer_add_file(ctx->importer, ctx->buffer);
12.303 - }
12.304 - if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
12.305 - ctx->state = YUM_STATE_BEGIN;
12.306 -}
12.307 -
12.308 -static int plover_system_arch_is_x86(void)
12.309 -{
12.310 - const char *arch=razor_system_arch();
12.311 - if (!arch || arch[0]!='i' || arch[1]<'3' || arch[1]>'6')
12.312 - return 0;
12.313 - else
12.314 - return !strcmp(arch+2,"86");
12.315 -}
12.316 -
12.317 -#define XML_BUFFER_SIZE 4096
12.318 -
12.319 -PloverRepository *plover_repository_new_from_yum_uri(const char *base_uri,
12.320 - GError **error)
12.321 -{
12.322 - struct yum_context ctx;
12.323 - gchar *s,**rpm_uris;
12.324 - GPtrArray *uris;
12.325 - char *uri;
12.326 - const char *name,*version,*arch;
12.327 - void *buf;
12.328 - gssize len;
12.329 - GInputStream *stream;
12.330 - GInputStream *primary,*filelists;
12.331 - GZlibDecompressor *decompressor;
12.332 - XML_ParsingStatus status;
12.333 - struct razor_set *razor;
12.334 - struct razor_package_iterator *iter;
12.335 - struct razor_package *pkg;
12.336 - PloverPackageSet *set;
12.337 - PloverRepository *repository;
12.338 - g_return_val_if_fail(plover__uri_validate(base_uri),NULL);
12.339 - plover__uri_handler_init();
12.340 - ctx.importer=razor_importer_create();
12.341 - ctx.state=YUM_STATE_BEGIN;
12.342 - ctx.base_uri=base_uri;
12.343 - ctx.primary_parser=XML_ParserCreate(NULL);
12.344 - XML_SetUserData(ctx.primary_parser,&ctx);
12.345 - XML_SetElementHandler(ctx.primary_parser,yum_primary_start_element,
12.346 - yum_primary_end_element);
12.347 - XML_SetCharacterDataHandler(ctx.primary_parser,yum_character_data);
12.348 - ctx.filelists_parser=XML_ParserCreate(NULL);
12.349 - XML_SetUserData(ctx.filelists_parser,&ctx);
12.350 - XML_SetElementHandler(ctx.filelists_parser,yum_filelists_start_element,
12.351 - yum_filelists_end_element);
12.352 - XML_SetCharacterDataHandler(ctx.filelists_parser,yum_character_data);
12.353 - uri=razor_path_relative_to_uri(base_uri,"repodata/primary.xml.gz",NULL);
12.354 - stream=plover_razor_input_stream_new(uri,error);
12.355 - free(uri);
12.356 - if (!stream) {
12.357 - XML_ParserFree(ctx.primary_parser);
12.358 - XML_ParserFree(ctx.filelists_parser);
12.359 - return NULL;
12.360 - }
12.361 - decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
12.362 - primary=g_converter_input_stream_new(G_INPUT_STREAM(stream),
12.363 - G_CONVERTER(decompressor));
12.364 - g_object_unref(stream);
12.365 - g_object_unref(decompressor);
12.366 - uri=razor_path_relative_to_uri(base_uri,"repodata/filelists.xml.gz",NULL);
12.367 - stream=plover_razor_input_stream_new(uri,error);
12.368 - free(uri);
12.369 - if (!stream) {
12.370 - g_object_unref(primary);
12.371 - XML_ParserFree(ctx.primary_parser);
12.372 - XML_ParserFree(ctx.filelists_parser);
12.373 - return NULL;
12.374 - }
12.375 - decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
12.376 - filelists=g_converter_input_stream_new(G_INPUT_STREAM(stream),
12.377 - G_CONVERTER(decompressor));
12.378 - g_object_unref(stream);
12.379 - g_object_unref(decompressor);
12.380 - ctx.current_parser=ctx.primary_parser;
12.381 - ctx.uris=g_tree_new_full((GCompareDataFunc)strcmp,NULL,g_free,NULL);
12.382 - ctx.current=0;
12.383 - do
12.384 - {
12.385 - XML_GetParsingStatus(ctx.current_parser,&status);
12.386 - switch (status.parsing)
12.387 - {
12.388 - case XML_SUSPENDED:
12.389 - XML_ResumeParser(ctx.current_parser);
12.390 - break;
12.391 - case XML_PARSING:
12.392 - case XML_INITIALIZED:
12.393 - buf=XML_GetBuffer(ctx.current_parser,XML_BUFFER_SIZE);
12.394 - if (ctx.current_parser==ctx.primary_parser)
12.395 - len=g_input_stream_read(G_INPUT_STREAM(primary),buf,
12.396 - XML_BUFFER_SIZE,NULL,error);
12.397 - else
12.398 - len=g_input_stream_read(G_INPUT_STREAM(filelists),buf,
12.399 - XML_BUFFER_SIZE,NULL,error);
12.400 - if (len<0)
12.401 - return NULL;
12.402 - XML_ParseBuffer(ctx.current_parser,len,!len);
12.403 - break;
12.404 - case XML_FINISHED:
12.405 - break;
12.406 - }
12.407 - } while (status.parsing!=XML_FINISHED);
12.408 - XML_ParserFree(ctx.primary_parser);
12.409 - XML_ParserFree(ctx.filelists_parser);
12.410 - g_object_unref(primary);
12.411 - g_object_unref(filelists);
12.412 - razor=razor_importer_finish(ctx.importer);
12.413 -#if RAZOR_HEADER_VERSION_MIN<=1
12.414 - /*
12.415 - * Header version 1 is supported by plover v0.3 and is used on
12.416 - * 32-bit intel machines which allows the setup and update
12.417 - * applications from v0.3 to work. On other machines, we don't
12.418 - * want these old applications to work (since they would do
12.419 - * the wrong thing) and so we use the current header version
12.420 - * which they don't support.
12.421 - */
12.422 - if (plover_system_arch_is_x86())
12.423 - razor_set_set_header_version(razor,1);
12.424 -#endif
12.425 - uris=g_ptr_array_new();
12.426 - iter=razor_package_iterator_create(razor);
12.427 - while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_NAME,&name,
12.428 - RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,RAZOR_DETAIL_LAST))
12.429 - {
12.430 - s=g_strconcat(name,"-",version,".",arch,NULL);
12.431 - g_ptr_array_add(uris,g_tree_lookup(ctx.uris,s));
12.432 - g_free(s);
12.433 - }
12.434 - razor_package_iterator_destroy(iter);
12.435 - g_ptr_array_add(uris,NULL);
12.436 - g_tree_unref(ctx.uris);
12.437 - rpm_uris=(gchar **)g_ptr_array_free(uris,FALSE);
12.438 - set=plover_package_set_new_from_razor(razor);
12.439 - razor_set_unref(razor);
12.440 - repository=plover_repository_new_from_package_set(set,
12.441 - (const char **)rpm_uris);
12.442 - g_object_unref(set);
12.443 - g_strfreev(rpm_uris);
12.444 - return repository;
12.445 -}
12.446 -
12.447 struct razor_set *plover_razor_set_create_from_yum_uri(const char *base_uri,
12.448 GError **error)
12.449 {
12.450 - PloverRepository *repository;
12.451 + PloverYumRepository *repository;
12.452 PloverPackageSet *set;
12.453 struct razor_set *razor;
12.454 g_return_val_if_fail(plover__uri_validate(base_uri),NULL);
12.455 - repository=plover_repository_new_from_yum_uri(base_uri,error);
12.456 + repository=plover_yum_repository_new_from_uri(base_uri,error);
12.457 if (!repository)
12.458 return NULL;
12.459 - set=plover_repository_get_package_set(repository);
12.460 + set=plover_repository_get_package_set(PLOVER_REPOSITORY(repository));
12.461 razor=plover_package_set_get_razor(set);
12.462 razor_set_ref(razor);
12.463 g_object_unref(repository);
13.1 --- a/plover/log.c Tue Jun 29 10:09:34 2021 +0100
13.2 +++ b/plover/log.c Tue Apr 25 17:41:00 2023 +0100
13.3 @@ -288,6 +288,7 @@
13.4
13.5 int plover_log_open(const char *path)
13.6 {
13.7 + static gchar *logfile=NULL;
13.8 int retval;
13.9 char *root;
13.10 gchar *filename,*uri;
13.11 @@ -367,7 +368,8 @@
13.12 g_free(filename);
13.13 return -1;
13.14 }
13.15 - g_free(filename);
13.16 + if (logfile)
13.17 + printf("Switching logging to %s on %s",filename,ctime(&t));
13.18 #ifdef WIN32
13.19 /*
13.20 * The situation under MS-Windows is a little complicated. If standard
13.21 @@ -402,7 +404,17 @@
13.22 SetStdHandle(STD_ERROR_HANDLE,(HANDLE)_get_osfhandle(2));
13.23 #endif
13.24 time(&t);
13.25 - printf("Run started on %s",ctime(&t));
13.26 + if (logfile)
13.27 + {
13.28 + printf("Logging switched from %s on %s",logfile,ctime(&t));
13.29 + g_free(logfile);
13.30 + logfile=filename;
13.31 + }
13.32 + else
13.33 + {
13.34 + printf("Run started on %s",ctime(&t));
13.35 + logfile=filename;
13.36 + }
13.37 fflush(stdout);
13.38 return 0;
13.39 }
14.1 --- a/plover/packageset.c Tue Jun 29 10:09:34 2021 +0100
14.2 +++ b/plover/packageset.c Tue Apr 25 17:41:00 2023 +0100
14.3 @@ -1,5 +1,5 @@
14.4 /*
14.5 - * Copyright (C) 2010-2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
14.6 + * Copyright (C) 2010-2012, 2014, 2023 J. Ali Harlow <ali@juiblex.co.uk>
14.7 *
14.8 * This program is free software; you can redistribute it and/or modify
14.9 * it under the terms of the GNU General Public License as published by
14.10 @@ -38,6 +38,7 @@
14.11 GSList *packages;
14.12 int no_details;
14.13 gchar *guessed_prefix;
14.14 + PloverRepository *repository;
14.15 } PloverPackageSetPrivate;
14.16
14.17 #define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
14.18 @@ -118,6 +119,7 @@
14.19 g_free(priv->root_uri);
14.20 priv->root_uri=NULL;
14.21 }
14.22 + g_clear_object(&priv->repository);
14.23 }
14.24
14.25 gboolean plover_package_set_open(PloverPackageSet *set,const char *root_uri,
14.26 @@ -354,9 +356,18 @@
14.27 priv->set=plover_package_set_get_razor(unrelocated);
14.28 razor_set_ref(priv->set);
14.29 }
14.30 + priv->repository=g_object_ref(repository);
14.31 return set;
14.32 }
14.33
14.34 +PloverRepository *plover_package_set_get_repository(PloverPackageSet *set)
14.35 +{
14.36 + PloverPackageSetPrivate *priv;
14.37 + g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
14.38 + priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
14.39 + return priv->repository;
14.40 +}
14.41 +
14.42 PloverPackageSet *plover_package_set_new_from_yum(const char *base,
14.43 struct razor_relocations *relocations,GError **error)
14.44 {
14.45 @@ -700,6 +711,9 @@
14.46 priv->guessed_prefix=plover_comps_get_default_prefix(comps);
14.47 plover_comps_free(comps);
14.48 }
14.49 + if (!priv->guessed_prefix)
14.50 + g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
14.51 + "No popular prefixes and no default prefix either");
14.52 return priv->guessed_prefix;
14.53 }
14.54
15.1 --- a/plover/packageset.h Tue Jun 29 10:09:34 2021 +0100
15.2 +++ b/plover/packageset.h Tue Apr 25 17:41:00 2023 +0100
15.3 @@ -49,6 +49,7 @@
15.4 PloverPackageSet *
15.5 plover_package_set_new_from_repository(PloverRepository *repository,
15.6 struct razor_relocations *relocations,GError **err);
15.7 +PloverRepository *plover_package_set_get_repository(PloverPackageSet *set);
15.8 PloverPackageSet *plover_package_set_new_from_yum(const char *base,
15.9 struct razor_relocations *relocations,GError **err);
15.10 PloverPackageSet *plover_package_set_new_from_rpms(const char **filenames,
16.1 --- a/plover/plover.h Tue Jun 29 10:09:34 2021 +0100
16.2 +++ b/plover/plover.h Tue Apr 25 17:41:00 2023 +0100
16.3 @@ -112,6 +112,7 @@
16.4 void plover_comps_set_vendor(struct comps *comps,const char *vendor);
16.5 void plover_comps_set_distribution(struct comps *comps,
16.6 const char *distribution);
16.7 +const char *plover_get_vendor_prefix(void);
16.8 gchar *plover_comps_get_default_prefix(struct comps *comps);
16.9
16.10 int plover_log_open(const char *path);
17.1 --- a/plover/plover.pc.in Tue Jun 29 10:09:34 2021 +0100
17.2 +++ b/plover/plover.pc.in Tue Apr 25 17:41:00 2023 +0100
17.3 @@ -6,6 +6,8 @@
17.4 Name: plover
17.5 Description: Plover packaging system
17.6 Version: @VERSION@
17.7 -Requires: razor expat zlib glib2
17.8 +Requires: @LIBPLOVER_REQUIREMENTS@
17.9 +Requires.private: @LIBPLOVER_PRIVATE_REQUIREMENTS@
17.10 Libs: -L${libdir} -lplover
17.11 +Libs.private: @LIBPLOVER_PRIVATE_LIBS@
17.12 Cflags: -I${includedir}
18.1 --- a/plover/repository.c Tue Jun 29 10:09:34 2021 +0100
18.2 +++ b/plover/repository.c Tue Apr 25 17:41:00 2023 +0100
18.3 @@ -19,12 +19,22 @@
18.4 #include "config.h"
18.5 #include <stdlib.h>
18.6 #include <string.h>
18.7 +#include <glib/gi18n.h>
18.8 #include <glib-object.h>
18.9 #include <razor.h>
18.10 #include <plover/plover.h>
18.11 #include <plover/repository.h>
18.12 #include "plover/uri-handler.h"
18.13
18.14 +enum {
18.15 + PROP_0,
18.16 + PROP_PACKAGE_SET,
18.17 + PROP_RPM_URIS,
18.18 + LAST_PROP
18.19 +};
18.20 +
18.21 +static GParamSpec *properties[LAST_PROP]={0};
18.22 +
18.23 G_DEFINE_TYPE(PloverRepository,plover_repository,G_TYPE_OBJECT);
18.24
18.25 typedef struct _PloverRepositoryPrivate {
18.26 @@ -53,12 +63,60 @@
18.27 G_OBJECT_CLASS(plover_repository_parent_class)->dispose(obj);
18.28 }
18.29
18.30 +static void plover_repository_set_property(GObject *obj,guint property_id,
18.31 + const GValue *value,GParamSpec *pspec)
18.32 +{
18.33 + PloverRepositoryPrivate *priv=PLOVER_REPOSITORY_GET_PRIVATE(obj);
18.34 + switch (property_id)
18.35 + {
18.36 + case PROP_PACKAGE_SET:
18.37 + g_clear_object(&priv->set);
18.38 + priv->set=g_value_dup_object(value);
18.39 + break;
18.40 + case PROP_RPM_URIS:
18.41 + g_strfreev(priv->uris);
18.42 + priv->uris=g_value_dup_boxed(value);
18.43 + break;
18.44 + default:
18.45 + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj,property_id,pspec);
18.46 + break;
18.47 + }
18.48 +}
18.49 +
18.50 +static void plover_repository_get_property(GObject *obj,guint property_id,
18.51 + GValue *value,GParamSpec *pspec)
18.52 +{
18.53 + PloverRepositoryPrivate *priv=PLOVER_REPOSITORY_GET_PRIVATE(obj);
18.54 + switch (property_id)
18.55 + {
18.56 + case PROP_PACKAGE_SET:
18.57 + g_value_set_object(value,priv->set);
18.58 + break;
18.59 + case PROP_RPM_URIS:
18.60 + g_value_set_boxed(value,priv->uris);
18.61 + break;
18.62 + default:
18.63 + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj,property_id,pspec);
18.64 + break;
18.65 + }
18.66 +}
18.67 +
18.68 static void plover_repository_class_init(PloverRepositoryClass *klass)
18.69 {
18.70 GObjectClass *oclass=G_OBJECT_CLASS(klass);
18.71 plover__uri_handler_init();
18.72 oclass->finalize=plover_repository_finalize;
18.73 oclass->dispose=plover_repository_dispose;
18.74 + oclass->set_property=plover_repository_set_property;
18.75 + oclass->get_property=plover_repository_get_property;
18.76 + g_object_class_install_property(oclass,PROP_PACKAGE_SET,
18.77 + g_param_spec_object("package-set",_("Package set"),
18.78 + _("The package set helper object"),PLOVER_TYPE_PACKAGE_SET,
18.79 + G_PARAM_STATIC_STRINGS|G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
18.80 + g_object_class_install_property(oclass,PROP_RPM_URIS,
18.81 + g_param_spec_boxed("rpm-uris",_("RPM URIs"),
18.82 + _("List of URIs, one for each RPM"),G_TYPE_STRV,
18.83 + G_PARAM_STATIC_STRINGS|G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
18.84 g_type_class_add_private(klass,sizeof(PloverRepositoryPrivate));
18.85 }
18.86
18.87 @@ -69,15 +127,10 @@
18.88 PloverRepository *plover_repository_new_from_package_set(PloverPackageSet *set,
18.89 const char **rpm_uris)
18.90 {
18.91 - PloverRepository *repository;
18.92 - PloverRepositoryPrivate *priv;
18.93 g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
18.94 g_return_val_if_fail(rpm_uris != NULL,NULL);
18.95 - repository=g_object_new(PLOVER_TYPE_REPOSITORY,NULL);
18.96 - priv=PLOVER_REPOSITORY_GET_PRIVATE(repository);
18.97 - priv->uris=g_strdupv((char **)rpm_uris);
18.98 - priv->set=g_object_ref(set);
18.99 - return repository;
18.100 + return g_object_new(PLOVER_TYPE_REPOSITORY,"package-set",set,
18.101 + "rpm-uris",rpm_uris,NULL);
18.102 }
18.103
18.104 PloverRepository *plover_repository_new_from_files(const char **filenames,
18.105 @@ -105,20 +158,6 @@
18.106 return repository;
18.107 }
18.108
18.109 -PloverRepository *plover_repository_new_from_yum(const char *base,
18.110 - GError **error)
18.111 -{
18.112 - PloverRepository *repository;
18.113 - gchar *base_uri;
18.114 - GFile *file;
18.115 - file=g_file_new_for_path(base);
18.116 - base_uri=g_file_get_uri(file);
18.117 - g_object_unref(file);
18.118 - repository=plover_repository_new_from_yum_uri(base_uri,error);
18.119 - g_free(base_uri);
18.120 - return repository;
18.121 -}
18.122 -
18.123 PloverPackageSet *
18.124 plover_repository_get_package_set(PloverRepository *repository)
18.125 {
19.1 --- a/plover/util.c Tue Jun 29 10:09:34 2021 +0100
19.2 +++ b/plover/util.c Tue Apr 25 17:41:00 2023 +0100
19.3 @@ -30,37 +30,49 @@
19.4 #include "plover.h"
19.5 #include "ascii-ctype.h"
19.6
19.7 -gchar *plover_comps_get_default_prefix(struct comps *comps)
19.8 +const char *plover_get_vendor_prefix(void)
19.9 {
19.10 - const char *vendor_prefix;
19.11 + static gchar *vendor_prefix=NULL; /* Leaked */
19.12 #ifdef WIN32
19.13 - /*
19.14 - * We want to sidestep any redirecting that MS-Windows may
19.15 - * introduce since this will be based on the architecture
19.16 - * of the installer whereas the architecture that actually
19.17 - * matters is of the packages (checked elsewhere).
19.18 - */
19.19 BOOL is_wow64=FALSE;
19.20 typedef BOOL (WINAPI *is_wow64_process_t)(HANDLE,PBOOL);
19.21 is_wow64_process_t is_wow64_process;
19.22 char *program_files=NULL;
19.23 char buf[PATH_MAX];
19.24 - is_wow64_process=(is_wow64_process_t)
19.25 - GetProcAddress(GetModuleHandleA("kernel32"),"IsWow64Process");
19.26 - if (is_wow64_process)
19.27 - is_wow64_process(GetCurrentProcess(),&is_wow64);
19.28 - if (is_wow64)
19.29 - program_files=getenv("ProgramW6432");
19.30 - if (!program_files)
19.31 +#endif
19.32 + if (!vendor_prefix)
19.33 {
19.34 - SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES|CSIDL_FLAG_DONT_VERIFY,NULL,0,
19.35 - buf);
19.36 - program_files=buf;
19.37 +#ifdef WIN32
19.38 + /*
19.39 + * We want to sidestep any redirecting that MS-Windows may
19.40 + * introduce since this will be based on the architecture
19.41 + * of the installer whereas the architecture that actually
19.42 + * matters is of the packages (checked elsewhere).
19.43 + */
19.44 + is_wow64_process=(is_wow64_process_t)
19.45 + GetProcAddress(GetModuleHandleA("kernel32"),"IsWow64Process");
19.46 + if (is_wow64_process)
19.47 + is_wow64_process(GetCurrentProcess(),&is_wow64);
19.48 + if (is_wow64)
19.49 + program_files=getenv("ProgramW6432");
19.50 + if (!program_files)
19.51 + {
19.52 + SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES|CSIDL_FLAG_DONT_VERIFY,
19.53 + NULL,0,buf);
19.54 + program_files=buf;
19.55 + }
19.56 + vendor_prefix=g_strdup(program_files);
19.57 +#else
19.58 + vendor_prefix=g_strdup(g_getenv("PLOVER_VENDOR_PREFIX"));
19.59 +#endif
19.60 }
19.61 - vendor_prefix=program_files;
19.62 -#else
19.63 - vendor_prefix=g_getenv("PLOVER_VENDOR_PREFIX");
19.64 -#endif
19.65 + return vendor_prefix;
19.66 +}
19.67 +
19.68 +gchar *plover_comps_get_default_prefix(struct comps *comps)
19.69 +{
19.70 + const char *vendor_prefix;
19.71 + vendor_prefix=plover_get_vendor_prefix();
19.72 if (!vendor_prefix)
19.73 return NULL;
19.74 else if (!comps)
19.75 @@ -156,13 +168,25 @@
19.76 if (!d)
19.77 {
19.78 if (g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT))
19.79 - g_mkdir_with_parents(path,0777);
19.80 + {
19.81 + if (g_mkdir_with_parents(path,0777))
19.82 + g_warning("Failed to create reports directory: %s: %s",path,
19.83 + g_strerror(errno));
19.84 + else
19.85 + g_message("0 reports found in %s",path);
19.86 + }
19.87 + else
19.88 + g_warning("Failed to open reports directory: %s: %s",path,
19.89 + err->message);
19.90 + g_clear_error(&err);
19.91 return;
19.92 }
19.93 while(count<=MAX_REPORTS && g_dir_read_name(d))
19.94 count++;
19.95 if (count>MAX_REPORTS)
19.96 {
19.97 + g_message("Purging %d report%s from %s",count-MAX_REPORTS,
19.98 + count-MAX_REPORTS==1?"":"s",path);
19.99 g_dir_rewind(d);
19.100 while((name=g_dir_read_name(d)))
19.101 {
19.102 @@ -188,6 +212,8 @@
19.103 files=g_list_delete_link(files,files);
19.104 }
19.105 }
19.106 + else
19.107 + g_message("%d report%s found in %s",count,count==1?"":"s",path);
19.108 g_dir_close(d);
19.109 }
19.110
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/plover/yumrepository.c Tue Apr 25 17:41:00 2023 +0100
20.3 @@ -0,0 +1,554 @@
20.4 +
20.5 +/*
20.6 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
20.7 + * Copyright (C) 2008 Red Hat, Inc
20.8 + * Copyright (C) 2009, 2011, 2014, 2016, 2023 J. Ali Harlow <ali@juiblex.co.uk>
20.9 + *
20.10 + * This program is free software; you can redistribute it and/or modify
20.11 + * it under the terms of the GNU General Public License as published by
20.12 + * the Free Software Foundation; either version 2 of the License, or
20.13 + * (at your option) any later version.
20.14 + *
20.15 + * This program is distributed in the hope that it will be useful,
20.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.18 + * GNU General Public License for more details.
20.19 + *
20.20 + * You should have received a copy of the GNU General Public License along
20.21 + * with this program; if not, write to the Free Software Foundation, Inc.,
20.22 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20.23 + */
20.24 +
20.25 +#define _GNU_SOURCE
20.26 +
20.27 +#include "config.h"
20.28 +#include <stdlib.h>
20.29 +#include <string.h>
20.30 +#include <stdio.h>
20.31 +#include <stdint.h>
20.32 +#include <sys/stat.h>
20.33 +#include <unistd.h>
20.34 +#include <fcntl.h>
20.35 +#include <errno.h>
20.36 +#include <glib.h>
20.37 +#include <glib-object.h>
20.38 +#include <expat.h>
20.39 +#include <zlib.h>
20.40 +#include <razor.h>
20.41 +#include <plover/plover.h>
20.42 +#include <plover/inputstream.h>
20.43 +#include <plover/yumrepository.h>
20.44 +#include <plover/uri-handler.h>
20.45 +
20.46 +G_DEFINE_TYPE(PloverYumRepository,plover_yum_repository,PLOVER_TYPE_REPOSITORY);
20.47 +
20.48 +typedef struct _PloverYumRepositoryPrivate {
20.49 + gchar *base_uri;
20.50 + struct comps *comps;
20.51 +} PloverYumRepositoryPrivate;
20.52 +
20.53 +#define PLOVER_YUM_REPOSITORY_GET_PRIVATE(obj)\
20.54 + G_TYPE_INSTANCE_GET_PRIVATE(obj,\
20.55 + PLOVER_TYPE_YUM_REPOSITORY,\
20.56 + PloverYumRepositoryPrivate)
20.57 +
20.58 +enum {
20.59 + YUM_STATE_BEGIN,
20.60 + YUM_STATE_PACKAGE_NAME,
20.61 + YUM_STATE_PACKAGE_ARCH,
20.62 + YUM_STATE_SUMMARY,
20.63 + YUM_STATE_DESCRIPTION,
20.64 + YUM_STATE_URL,
20.65 + YUM_STATE_LICENSE,
20.66 + YUM_STATE_CHECKSUM,
20.67 + YUM_STATE_REQUIRES,
20.68 + YUM_STATE_PROVIDES,
20.69 + YUM_STATE_OBSOLETES,
20.70 + YUM_STATE_CONFLICTS,
20.71 + YUM_STATE_SKIPPING_PACKAGE,
20.72 + YUM_STATE_FILE
20.73 +};
20.74 +
20.75 +struct yum_context {
20.76 + XML_Parser primary_parser;
20.77 + XML_Parser filelists_parser;
20.78 + XML_Parser current_parser;
20.79 +
20.80 + struct razor_importer *importer;
20.81 + struct import_property_context *current_property_context;
20.82 + const char *base_uri;
20.83 + GTree *uris;
20.84 + char name[256], arch[64], summary[512], description[4096];
20.85 + char url[256], license[64], buffer[512], *p;
20.86 + char pkgid[128], evr[128];
20.87 + uint32_t property_type;
20.88 + int state;
20.89 +
20.90 + int total, current;
20.91 +};
20.92 +
20.93 +static void plover_yum_repository_finalize(GObject *obj)
20.94 +{
20.95 + PloverYumRepositoryPrivate *priv=PLOVER_YUM_REPOSITORY_GET_PRIVATE(obj);
20.96 + plover_comps_free(priv->comps);
20.97 + g_free(priv->base_uri);
20.98 + if (G_OBJECT_CLASS(plover_yum_repository_parent_class)->finalize)
20.99 + G_OBJECT_CLASS(plover_yum_repository_parent_class)->finalize(obj);
20.100 +}
20.101 +
20.102 +static void plover_yum_repository_class_init(PloverYumRepositoryClass *klass)
20.103 +{
20.104 + GObjectClass *oclass=G_OBJECT_CLASS(klass);
20.105 + plover__uri_handler_init();
20.106 + oclass->finalize=plover_yum_repository_finalize;
20.107 + g_type_class_add_private(klass,sizeof(PloverYumRepositoryPrivate));
20.108 +}
20.109 +
20.110 +static void plover_yum_repository_init(PloverYumRepository *repository)
20.111 +{
20.112 +}
20.113 +
20.114 +static uint32_t
20.115 +yum_to_razor_relation (const char *flags)
20.116 +{
20.117 + if (flags[0] == 'L') {
20.118 + if (flags[1] == 'T')
20.119 + return RAZOR_PROPERTY_LESS;
20.120 + else
20.121 + return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
20.122 + } else if (flags[0] == 'G') {
20.123 + if (flags[1] == 'T')
20.124 + return RAZOR_PROPERTY_GREATER;
20.125 + else
20.126 + return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
20.127 + } else
20.128 + return RAZOR_PROPERTY_EQUAL;
20.129 +}
20.130 +
20.131 +static void
20.132 +yum_primary_start_element(void *data, const char *name, const char **atts)
20.133 +{
20.134 + struct yum_context *ctx = data;
20.135 + const char *n, *epoch, *version, *release;
20.136 + char buffer[128];
20.137 + char *s;
20.138 + gchar *nevra;
20.139 + uint32_t pre, relation, flags;
20.140 + int i;
20.141 +
20.142 + if (ctx->state == YUM_STATE_SKIPPING_PACKAGE)
20.143 + return;
20.144 +
20.145 + if (strcmp(name, "metadata") == 0) {
20.146 + for (i = 0; atts[i]; i += 2) {
20.147 + if (strcmp(atts[i], "packages") == 0)
20.148 + ctx->total = atoi(atts[i + 1]);
20.149 + }
20.150 + } else if (strcmp(name, "package") == 0) {
20.151 + *ctx->name=*ctx->arch=*ctx->summary=*ctx->description='\0';
20.152 + *ctx->url=*ctx->license='\0';
20.153 + } else if (strcmp(name, "name") == 0) {
20.154 + ctx->state = YUM_STATE_PACKAGE_NAME;
20.155 + ctx->p = ctx->name;
20.156 + } else if (strcmp(name, "arch") == 0) {
20.157 + ctx->state = YUM_STATE_PACKAGE_ARCH;
20.158 + ctx->p = ctx->arch;
20.159 + } else if (strcmp(name, "version") == 0) {
20.160 + epoch = NULL;
20.161 + version = NULL;
20.162 + release = NULL;
20.163 + for (i = 0; atts[i]; i += 2) {
20.164 + if (strcmp(atts[i], "epoch") == 0)
20.165 + epoch = atts[i + 1];
20.166 + else if (strcmp(atts[i], "ver") == 0)
20.167 + version = atts[i + 1];
20.168 + else if (strcmp(atts[i], "rel") == 0)
20.169 + release = atts[i + 1];
20.170 + }
20.171 + if (version == NULL || release == NULL) {
20.172 + fprintf(stderr, "invalid version tag, "
20.173 + "missing version or release attribute\n");
20.174 + return;
20.175 + }
20.176 +
20.177 + razor_build_evr(ctx->evr, sizeof ctx->evr, epoch, version,
20.178 + release);
20.179 + if (!strcmp(ctx->arch, "noarch") ||
20.180 + !strcmp(ctx->arch, razor_system_arch())) {
20.181 + razor_importer_begin_package(ctx->importer, ctx->name,
20.182 + ctx->evr, ctx->arch);
20.183 + } else
20.184 + ctx->state = YUM_STATE_SKIPPING_PACKAGE;
20.185 + } else if (strcmp(name, "summary") == 0) {
20.186 + ctx->p = ctx->summary;
20.187 + ctx->state = YUM_STATE_SUMMARY;
20.188 + } else if (strcmp(name, "description") == 0) {
20.189 + ctx->p = ctx->description;
20.190 + ctx->state = YUM_STATE_DESCRIPTION;
20.191 + } else if (strcmp(name, "url") == 0) {
20.192 + ctx->p = ctx->url;
20.193 + ctx->state = YUM_STATE_URL;
20.194 + } else if (strcmp(name, "checksum") == 0) {
20.195 + ctx->p = ctx->pkgid;
20.196 + ctx->state = YUM_STATE_CHECKSUM;
20.197 + } else if (strcmp(name, "location") == 0) {
20.198 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
20.199 + for (i = 0; atts[i]; i += 2)
20.200 + if (strcmp(atts[i], "href") == 0) {
20.201 + nevra=g_strconcat(ctx->name,"-",ctx->evr,".",
20.202 + ctx->arch,NULL);
20.203 + s=razor_path_relative_to_uri(ctx->base_uri,
20.204 + atts[i + 1],NULL);
20.205 + g_tree_insert(ctx->uris,nevra,g_strdup(s));
20.206 + free(s);
20.207 + break;
20.208 + }
20.209 + }
20.210 + } else if (strcmp(name, "rpm:license") == 0) {
20.211 + ctx->p = ctx->license;
20.212 + ctx->state = YUM_STATE_LICENSE;
20.213 + } else if (strcmp(name, "rpm:requires") == 0) {
20.214 + ctx->state = YUM_STATE_REQUIRES;
20.215 + ctx->property_type = RAZOR_PROPERTY_REQUIRES;
20.216 + } else if (strcmp(name, "rpm:provides") == 0) {
20.217 + ctx->state = YUM_STATE_PROVIDES;
20.218 + ctx->property_type = RAZOR_PROPERTY_PROVIDES;
20.219 + } else if (strcmp(name, "rpm:obsoletes") == 0) {
20.220 + ctx->state = YUM_STATE_OBSOLETES;
20.221 + ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
20.222 + } else if (strcmp(name, "rpm:conflicts") == 0) {
20.223 + ctx->state = YUM_STATE_CONFLICTS;
20.224 + ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
20.225 + } else if (strcmp(name, "rpm:entry") == 0 &&
20.226 + ctx->state != YUM_STATE_BEGIN) {
20.227 + n = NULL;
20.228 + epoch = NULL;
20.229 + version = NULL;
20.230 + release = NULL;
20.231 + relation = RAZOR_PROPERTY_EQUAL;
20.232 + pre = 0;
20.233 + for (i = 0; atts[i]; i += 2) {
20.234 + if (strcmp(atts[i], "name") == 0)
20.235 + n = atts[i + 1];
20.236 + else if (strcmp(atts[i], "epoch") == 0)
20.237 + epoch = atts[i + 1];
20.238 + else if (strcmp(atts[i], "ver") == 0)
20.239 + version = atts[i + 1];
20.240 + else if (strcmp(atts[i], "rel") == 0)
20.241 + release = atts[i + 1];
20.242 + else if (strcmp(atts[i], "flags") == 0)
20.243 + relation = yum_to_razor_relation(atts[i + 1]);
20.244 + else if (strcmp(atts[i], "pre") == 0)
20.245 + pre = RAZOR_PROPERTY_PRE;
20.246 + }
20.247 +
20.248 + if (n == NULL) {
20.249 + fprintf(stderr, "invalid rpm:entry, "
20.250 + "missing name or version attributes\n");
20.251 + return;
20.252 + }
20.253 +
20.254 + razor_build_evr(buffer, sizeof buffer, epoch, version, release);
20.255 + flags = ctx->property_type | relation | pre;
20.256 + razor_importer_add_property(ctx->importer, n, flags, buffer);
20.257 + }
20.258 +}
20.259 +
20.260 +static void
20.261 +yum_primary_end_element (void *data, const char *name)
20.262 +{
20.263 + struct yum_context *ctx = data;
20.264 +
20.265 + switch (ctx->state) {
20.266 + case YUM_STATE_PACKAGE_NAME:
20.267 + case YUM_STATE_PACKAGE_ARCH:
20.268 + case YUM_STATE_SUMMARY:
20.269 + case YUM_STATE_DESCRIPTION:
20.270 + case YUM_STATE_URL:
20.271 + case YUM_STATE_LICENSE:
20.272 + case YUM_STATE_CHECKSUM:
20.273 + case YUM_STATE_FILE:
20.274 + ctx->state = YUM_STATE_BEGIN;
20.275 + break;
20.276 + }
20.277 +
20.278 + if (strcmp(name, "package") == 0) {
20.279 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
20.280 + razor_importer_add_details(ctx->importer, ctx->summary,
20.281 + ctx->description, ctx->url,
20.282 + ctx->license);
20.283 +
20.284 + XML_StopParser(ctx->current_parser, XML_TRUE);
20.285 + ctx->current_parser = ctx->filelists_parser;
20.286 + }
20.287 +}
20.288 +
20.289 +static void
20.290 +yum_character_data (void *data, const XML_Char *s, int len)
20.291 +{
20.292 + struct yum_context *ctx = data;
20.293 +
20.294 + switch (ctx->state) {
20.295 + case YUM_STATE_PACKAGE_NAME:
20.296 + case YUM_STATE_PACKAGE_ARCH:
20.297 + case YUM_STATE_SUMMARY:
20.298 + case YUM_STATE_DESCRIPTION:
20.299 + case YUM_STATE_URL:
20.300 + case YUM_STATE_LICENSE:
20.301 + case YUM_STATE_CHECKSUM:
20.302 + case YUM_STATE_FILE:
20.303 + memcpy(ctx->p, s, len);
20.304 + ctx->p += len;
20.305 + *ctx->p = '\0';
20.306 + break;
20.307 + }
20.308 +}
20.309 +
20.310 +static void
20.311 +yum_filelists_start_element(void *data, const char *name, const char **atts)
20.312 +{
20.313 + struct yum_context *ctx = data;
20.314 + const char *pkg, *pkgid;
20.315 + int i;
20.316 +
20.317 + if (strcmp(name, "package") == 0 &&
20.318 + ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
20.319 + pkg = NULL;
20.320 + pkgid = NULL;
20.321 + for (i = 0; atts[i]; i += 2) {
20.322 + if (strcmp(atts[i], "name") == 0)
20.323 + pkg = atts[i + 1];
20.324 + else if (strcmp(atts[i], "pkgid") == 0)
20.325 + pkgid = atts[i + 1];
20.326 + }
20.327 + if (strcmp(pkgid, ctx->pkgid) != 0)
20.328 + fprintf(stderr, "primary.xml and filelists.xml "
20.329 + "mismatch for %s: %s vs %s",
20.330 + pkg, pkgid, ctx->pkgid);
20.331 + } else if (strcmp(name, "file") == 0) {
20.332 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
20.333 + ctx->state = YUM_STATE_FILE;
20.334 + ctx->p = ctx->buffer;
20.335 + }
20.336 +}
20.337 +
20.338 +static void
20.339 +yum_filelists_end_element (void *data, const char *name)
20.340 +{
20.341 + struct yum_context *ctx = data;
20.342 +
20.343 + if (strcmp(name, "package") == 0) {
20.344 + XML_StopParser(ctx->current_parser, XML_TRUE);
20.345 + ctx->current_parser = ctx->primary_parser;
20.346 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
20.347 + razor_importer_finish_package(ctx->importer);
20.348 + ctx->state = YUM_STATE_BEGIN;
20.349 + } else if (strcmp(name, "file") == 0) {
20.350 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
20.351 + razor_importer_add_file(ctx->importer, ctx->buffer);
20.352 + }
20.353 + if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
20.354 + ctx->state = YUM_STATE_BEGIN;
20.355 +}
20.356 +
20.357 +static int plover_system_arch_is_x86(void)
20.358 +{
20.359 + const char *arch=razor_system_arch();
20.360 + if (!arch || arch[0]!='i' || arch[1]<'3' || arch[1]>'6')
20.361 + return 0;
20.362 + else
20.363 + return !strcmp(arch+2,"86");
20.364 +}
20.365 +
20.366 +#define XML_BUFFER_SIZE 4096
20.367 +
20.368 +PloverYumRepository *plover_yum_repository_new_from_uri(const char *base_uri,
20.369 + GError **error)
20.370 +{
20.371 + struct yum_context ctx;
20.372 + gchar *s,**rpm_uris;
20.373 + GPtrArray *uris;
20.374 + char *uri;
20.375 + const char *name,*version,*arch;
20.376 + void *buf;
20.377 + gssize len;
20.378 + GInputStream *stream;
20.379 + GInputStream *primary,*filelists;
20.380 + GZlibDecompressor *decompressor;
20.381 + XML_ParsingStatus status;
20.382 + struct razor_set *razor;
20.383 + struct razor_package_iterator *iter;
20.384 + struct razor_package *pkg;
20.385 + PloverPackageSet *set;
20.386 + PloverYumRepository *repository;
20.387 + PloverYumRepositoryPrivate *priv;
20.388 + g_return_val_if_fail(plover__uri_validate(base_uri),NULL);
20.389 + ctx.importer=razor_importer_create();
20.390 + ctx.state=YUM_STATE_BEGIN;
20.391 + ctx.base_uri=base_uri;
20.392 + ctx.primary_parser=XML_ParserCreate(NULL);
20.393 + XML_SetUserData(ctx.primary_parser,&ctx);
20.394 + XML_SetElementHandler(ctx.primary_parser,yum_primary_start_element,
20.395 + yum_primary_end_element);
20.396 + XML_SetCharacterDataHandler(ctx.primary_parser,yum_character_data);
20.397 + ctx.filelists_parser=XML_ParserCreate(NULL);
20.398 + XML_SetUserData(ctx.filelists_parser,&ctx);
20.399 + XML_SetElementHandler(ctx.filelists_parser,yum_filelists_start_element,
20.400 + yum_filelists_end_element);
20.401 + XML_SetCharacterDataHandler(ctx.filelists_parser,yum_character_data);
20.402 + uri=razor_path_relative_to_uri(base_uri,"repodata/primary.xml.gz",NULL);
20.403 + stream=plover_razor_input_stream_new(uri,error);
20.404 + free(uri);
20.405 + if (!stream) {
20.406 + XML_ParserFree(ctx.primary_parser);
20.407 + XML_ParserFree(ctx.filelists_parser);
20.408 + return NULL;
20.409 + }
20.410 + decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
20.411 + primary=g_converter_input_stream_new(G_INPUT_STREAM(stream),
20.412 + G_CONVERTER(decompressor));
20.413 + g_object_unref(stream);
20.414 + g_object_unref(decompressor);
20.415 + uri=razor_path_relative_to_uri(base_uri,"repodata/filelists.xml.gz",NULL);
20.416 + stream=plover_razor_input_stream_new(uri,error);
20.417 + free(uri);
20.418 + if (!stream) {
20.419 + g_object_unref(primary);
20.420 + XML_ParserFree(ctx.primary_parser);
20.421 + XML_ParserFree(ctx.filelists_parser);
20.422 + return NULL;
20.423 + }
20.424 + decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
20.425 + filelists=g_converter_input_stream_new(G_INPUT_STREAM(stream),
20.426 + G_CONVERTER(decompressor));
20.427 + g_object_unref(stream);
20.428 + g_object_unref(decompressor);
20.429 + ctx.current_parser=ctx.primary_parser;
20.430 + ctx.uris=g_tree_new_full((GCompareDataFunc)strcmp,NULL,g_free,NULL);
20.431 + ctx.current=0;
20.432 + do
20.433 + {
20.434 + XML_GetParsingStatus(ctx.current_parser,&status);
20.435 + switch (status.parsing)
20.436 + {
20.437 + case XML_SUSPENDED:
20.438 + XML_ResumeParser(ctx.current_parser);
20.439 + break;
20.440 + case XML_PARSING:
20.441 + case XML_INITIALIZED:
20.442 + buf=XML_GetBuffer(ctx.current_parser,XML_BUFFER_SIZE);
20.443 + if (ctx.current_parser==ctx.primary_parser)
20.444 + len=g_input_stream_read(G_INPUT_STREAM(primary),buf,
20.445 + XML_BUFFER_SIZE,NULL,error);
20.446 + else
20.447 + len=g_input_stream_read(G_INPUT_STREAM(filelists),buf,
20.448 + XML_BUFFER_SIZE,NULL,error);
20.449 + if (len<0)
20.450 + return NULL;
20.451 + XML_ParseBuffer(ctx.current_parser,len,!len);
20.452 + break;
20.453 + case XML_FINISHED:
20.454 + break;
20.455 + }
20.456 + } while (status.parsing!=XML_FINISHED);
20.457 + XML_ParserFree(ctx.primary_parser);
20.458 + XML_ParserFree(ctx.filelists_parser);
20.459 + g_object_unref(primary);
20.460 + g_object_unref(filelists);
20.461 + razor=razor_importer_finish(ctx.importer);
20.462 +#if RAZOR_HEADER_VERSION_MIN<=1
20.463 + /*
20.464 + * Header version 1 is supported by plover v0.3 and is used on
20.465 + * 32-bit intel machines which allows the setup and update
20.466 + * applications from v0.3 to work. On other machines, we don't
20.467 + * want these old applications to work (since they would do
20.468 + * the wrong thing) and so we use the current header version
20.469 + * which they don't support.
20.470 + */
20.471 + if (plover_system_arch_is_x86())
20.472 + razor_set_set_header_version(razor,1);
20.473 +#endif
20.474 + uris=g_ptr_array_new();
20.475 + iter=razor_package_iterator_create(razor);
20.476 + while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_NAME,&name,
20.477 + RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,RAZOR_DETAIL_LAST))
20.478 + {
20.479 + s=g_strconcat(name,"-",version,".",arch,NULL);
20.480 + g_ptr_array_add(uris,g_tree_lookup(ctx.uris,s));
20.481 + g_free(s);
20.482 + }
20.483 + razor_package_iterator_destroy(iter);
20.484 + g_ptr_array_add(uris,NULL);
20.485 + g_tree_unref(ctx.uris);
20.486 + rpm_uris=(gchar **)g_ptr_array_free(uris,FALSE);
20.487 + set=plover_package_set_new_from_razor(razor);
20.488 + razor_set_unref(razor);
20.489 + repository=g_object_new(PLOVER_TYPE_YUM_REPOSITORY,"package-set",set,
20.490 + "rpm-uris",rpm_uris,NULL);
20.491 + g_object_unref(set);
20.492 + g_strfreev(rpm_uris);
20.493 + priv=PLOVER_YUM_REPOSITORY_GET_PRIVATE(repository);
20.494 + priv->base_uri=g_strdup(base_uri);
20.495 + return repository;
20.496 +}
20.497 +
20.498 +PloverYumRepository *plover_yum_repository_new_from_path(const char *base,
20.499 + GError **error)
20.500 +{
20.501 + PloverYumRepository *repository;
20.502 + gchar *base_uri;
20.503 + GFile *file;
20.504 + file=g_file_new_for_path(base);
20.505 + base_uri=g_file_get_uri(file);
20.506 + g_object_unref(file);
20.507 + repository=plover_yum_repository_new_from_uri(base_uri,error);
20.508 + g_free(base_uri);
20.509 + return repository;
20.510 +}
20.511 +
20.512 +/* Compatibility function: Depreciated in favour of
20.513 + * plover_yum_repository_new_from_uri()
20.514 + */
20.515 +
20.516 +PloverRepository *plover_repository_new_from_yum_uri(const char *base_uri,
20.517 + GError **error)
20.518 +{
20.519 + PloverYumRepository *repository;
20.520 + repository=plover_yum_repository_new_from_uri(base_uri,error);
20.521 + return repository?PLOVER_REPOSITORY(repository):NULL;
20.522 +}
20.523 +
20.524 +/* Compatibility function: Depreciated in favour of
20.525 + * plover_yum_repository_new_from_path()
20.526 + */
20.527 +
20.528 +PloverRepository *plover_repository_new_from_yum(const char *base,
20.529 + GError **error)
20.530 +{
20.531 + PloverYumRepository *repository;
20.532 + repository=plover_yum_repository_new_from_path(base,error);
20.533 + return repository?PLOVER_REPOSITORY(repository):NULL;
20.534 +}
20.535 +
20.536 +struct comps *plover_yum_repository_get_comps(PloverYumRepository *repository,
20.537 + GError **error)
20.538 +{
20.539 + gchar *uri;
20.540 + PloverYumRepositoryPrivate *priv;
20.541 + g_return_val_if_fail(PLOVER_IS_YUM_REPOSITORY(repository),NULL);
20.542 + priv=PLOVER_YUM_REPOSITORY_GET_PRIVATE(repository);
20.543 + if (!priv->base_uri)
20.544 + {
20.545 + g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
20.546 + "No base URI set");
20.547 + return NULL;
20.548 + }
20.549 + if (!priv->comps)
20.550 + {
20.551 + uri=razor_path_relative_to_uri(priv->base_uri,"repodata/comps.xml",
20.552 + NULL);
20.553 + priv->comps=plover_comps_new_from_uri(uri,error);
20.554 + free(uri);
20.555 + }
20.556 + return priv->comps;
20.557 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/plover/yumrepository.h Tue Apr 25 17:41:00 2023 +0100
21.3 @@ -0,0 +1,46 @@
21.4 +#ifndef __PLOVER_YUM_REPOSITORY_H__
21.5 +#define __PLOVER_YUM_REPOSITORY_H__
21.6 +
21.7 +#include <plover/repository.h>
21.8 +
21.9 +G_BEGIN_DECLS
21.10 +
21.11 +#define PLOVER_TYPE_YUM_REPOSITORY \
21.12 + plover_yum_repository_get_type()
21.13 +#define PLOVER_YUM_REPOSITORY(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,\
21.14 + PLOVER_TYPE_YUM_REPOSITORY,\
21.15 + PloverYumRepository)
21.16 +#define PLOVER_YUM_REPOSITORY_CLASS(klass)\
21.17 + G_TYPE_CHECK_CLASS_CAST(klass,\
21.18 + PLOVER_TYPE_YUM_REPOSITORY,\
21.19 + PloverYumRepositoryClass)
21.20 +#define PLOVER_IS_YUM_REPOSITORY(obj)\
21.21 + G_TYPE_CHECK_INSTANCE_TYPE(obj,\
21.22 + PLOVER_TYPE_YUM_REPOSITORY)
21.23 +#define PLOVER_IS_YUM_REPOSITORY_CLASS(klass)\
21.24 + G_TYPE_CHECK_CLASS_TYPE(obj,\
21.25 + PLOVER_TYPE_YUM_REPOSITORY)
21.26 +#define PLOVER_YUM_REPOSITORY_GET_CLASS(obj)\
21.27 + G_TYPE_INSTANCE_GET_CLASS(obj,\
21.28 + PLOVER_TYPE_YUM_REPOSITORY,\
21.29 + PloverYumRepositoryClass)
21.30 +
21.31 +typedef struct _PloverYumRepository {
21.32 + PloverRepository parent_instance;
21.33 +} PloverYumRepository;
21.34 +
21.35 +typedef struct _PloverYumRepositoryClass {
21.36 + PloverRepositoryClass parent_class;
21.37 +} PloverYumRepositoryClass;
21.38 +
21.39 +GType plover_yum_repository_get_type(void) G_GNUC_CONST;
21.40 +PloverYumRepository *plover_yum_repository_new_from_uri(const char *base_uri,
21.41 + GError **error);
21.42 +PloverYumRepository *plover_yum_repository_new_from_path(const char *base,
21.43 + GError **error);
21.44 +struct comps *plover_yum_repository_get_comps(PloverYumRepository *repository,
21.45 + GError **error);
21.46 +
21.47 +G_END_DECLS
21.48 +
21.49 +#endif /* __PLOVER_YUM_REPOSITORY_H__ */
22.1 --- a/pre-inst/pre-inst.c Tue Jun 29 10:09:34 2021 +0100
22.2 +++ b/pre-inst/pre-inst.c Tue Apr 25 17:41:00 2023 +0100
22.3 @@ -48,12 +48,13 @@
22.4 #endif /* WIN32 */
22.5 #include "post.h"
22.6
22.7 -#ifdef WIN32
22.8 -/* Under WIN32, g_spawn requires a helper program which we'd rather avoid */
22.9 -#undef USE_G_SPAWN
22.10 -#else
22.11 +/*
22.12 + * Under WIN32, g_spawn may require a helper program which we'd rather avoid.
22.13 + * At least with glib 2.58, this isn't needed if g_spawn_sync() is used (or
22.14 + * G_SPAWN_DO_NOT_REAP_CHILD is specified), so we can now define USE_G_SPAWN
22.15 + * unconditionally.
22.16 + */
22.17 #define USE_G_SPAWN
22.18 -#endif
22.19
22.20 LUALIB_API int luaopen_posix(lua_State *L);
22.21
22.22 @@ -376,6 +377,7 @@
22.23 "Post command exited with code %ld",(long)rc);
22.24 return FALSE;
22.25 }
22.26 + fprintf(stderr,"post command exited normally\n");
22.27 return TRUE;
22.28 }
22.29
22.30 @@ -422,6 +424,29 @@
22.31 return TRUE;
22.32 }
22.33
22.34 +print_arguments(int argc,char **argv)
22.35 +{
22.36 + int i,j;
22.37 + for(i=0;i<argc;i++)
22.38 + {
22.39 + if (i)
22.40 + putchar(' ');
22.41 + if (strchr(argv[i],' ') || strchr(argv[i],'"') || strchr(argv[i],'\n'))
22.42 + {
22.43 + putchar('"');
22.44 + for(j=0;argv[i][j];j++)
22.45 + {
22.46 + if (strchr("$`\"\\\n",argv[i][j]))
22.47 + putchar('\\');
22.48 + putchar(argv[i][j]);
22.49 + }
22.50 + putchar('"');
22.51 + }
22.52 + else
22.53 + fputs(argv[i],stdout);
22.54 + }
22.55 +}
22.56 +
22.57 /*
22.58 * Run a command after completing request.
22.59 *
22.60 @@ -446,7 +471,6 @@
22.61 "--post: No command given");
22.62 return FALSE;
22.63 }
22.64 - printf("Running post command: %s\n",argv[1]);
22.65 if (!g_shell_parse_argv(argv[1],&post_argc,&post_argv,&tmp_error))
22.66 {
22.67 g_propagate_prefixed_error(error,tmp_error,"%s: ",argv[1]);
22.68 @@ -482,6 +506,9 @@
22.69 post_argv[i]=expanded;
22.70 }
22.71 }
22.72 + printf("Running post command: ");
22.73 + print_arguments(post_argc,post_argv);
22.74 + putchar('\n');
22.75 return pre_install_spawn_sync(post_argv,error);
22.76 }
22.77
22.78 @@ -593,7 +620,12 @@
22.79 }
22.80 }
22.81 if (post && post->argc>0)
22.82 + {
22.83 + printf("Running post command: ");
22.84 + print_arguments(post->argc,post->argv);
22.85 + putchar('\n');
22.86 pre_install_spawn_sync(post->argv,&error);
22.87 + }
22.88 else if (argv)
22.89 run_post(argc,argv,success,repository,&error);
22.90 if (post)