Add GUI front-end to setup and update
authorJ. Ali Harlow <ali@juiblex.co.uk>
Sat Nov 15 19:04:45 2014 +0000 (2014-11-15)
changeset 242b9f54d14cc2
parent 22 5cbb66c24fc6
child 25 e10f418d8e1d
Add GUI front-end to setup and update
.gitignore
Makefile.am
app-manager/Makefile.am
app-manager/app-manager.c
app-manager/app-manager.h
app-manager/app-manager.ui
app-manager/applications.c
app-manager/fetch.c
app-manager/localmedia.c
app-manager/packagelist.c
app-manager/resources.rc.in
app-manager/setup.c
app-manager/update.c
configure.ac
plover-gtk/Makefile.am
plover-gtk/error.c
plover-gtk/error.h
plover-gtk/package.c
plover-gtk/package.h
plover-gtk/packagefilestore.c
plover-gtk/packagefilestore.h
plover-gtk/packageset.c
plover-gtk/packageset.h
plover-gtk/packagestore.c
plover-gtk/packagestore.h
plover-gtk/software-installation.ui
plover-gtk/stockicons.c
plover-gtk/stockicons.h
plover-gtk/transactionhelper.c
plover-gtk/transactionhelper.h
plover/Makefile.am
plover/import-yum.c
plover/log.c
plover/package.c
plover/package.h
plover/packageset.c
plover/packageset.h
plover/plover.h
plover/plover.pc.in
plover/razor.c
plover/repository.c
plover/repository.h
plover/transaction.c
plover/transaction.h
plover/util.c
plover/vector.c
pre-inst/Makefile.am
pre-inst/icon16.png
pre-inst/icon22.png
pre-inst/icon32.png
pre-inst/manifest.xml.in
pre-inst/pre-inst.c
pre-inst/resource.h
pre-inst/resources.rc.in
setup/Makefile.am
setup/resources.rc.in
setup/setup.c
setup/setup.js.in
update/Makefile.am
update/resources.rc.in
update/update.c
update/update.js.in
     1.1 --- a/.gitignore	Fri Mar 23 20:29:50 2012 +0000
     1.2 +++ b/.gitignore	Sat Nov 15 19:04:45 2014 +0000
     1.3 @@ -13,10 +13,26 @@
     1.4  *.o
     1.5  *.lo
     1.6  *.la
     1.7 +*.ico
     1.8 +*.exe
     1.9 +*.exe.manifest
    1.10  plover/plover.pc
    1.11  plover-gtk/plover-gtk.pc
    1.12  setup/resources.rc
    1.13  setup/setup
    1.14 +setup/setup.js
    1.15 +setup/icon*.pnm
    1.16  update/resources.rc
    1.17  update/update
    1.18 +update/update.js
    1.19 +update/icon*.pnm
    1.20 +pre-inst/resources.rc
    1.21 +pre-inst/pre-inst
    1.22 +pre-inst/icon*.pnm
    1.23  app-manager/resources.rc
    1.24 +app-manager/fetch
    1.25 +app-manager/app-manager
    1.26 +app-manager/plover-applications*.pgm
    1.27 +app-manager/plover-applications*.pnm
    1.28 +app-manager/24x24
    1.29 +app-manager/48x48
     2.1 --- a/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
     2.2 +++ b/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
     2.3 @@ -1,1 +1,1 @@
     2.4 -SUBDIRS=plover setup update plover-gtk app-manager
     2.5 +SUBDIRS=plover setup update pre-inst plover-gtk app-manager
     3.1 --- a/app-manager/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
     3.2 +++ b/app-manager/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
     3.3 @@ -3,12 +3,15 @@
     3.4  
     3.5  bin_PROGRAMS=app-manager fetch
     3.6  app_manager_SOURCES=app-manager.c app-manager.h packagelist.c applications.c \
     3.7 -	localmedia.c localmedia.h
     3.8 +	localmedia.c localmedia.h setup.c update.c
     3.9  fetch_SOURCES=fetch.c
    3.10  fetch_LDADD=$(LDADD) $(FETCH_LIBS)
    3.11  if HAVE_WINDRES
    3.12  app_manager_SOURCES+=resources.rc app-manager.exe.manifest
    3.13  endif
    3.14 +if PLOVER_MINGW
    3.15 +app_manager_LDFLAGS=-mwindows
    3.16 +endif
    3.17  uidir=$(pkgdatadir)
    3.18  ui_DATA=app-manager.ui
    3.19  desktopdir=$(datadir)/applications
    3.20 @@ -20,34 +23,39 @@
    3.21  bigicondir=$(datadir)/icons/hicolor/48x48/apps
    3.22  bigicon_DATA=48x48/plover-applications.png
    3.23  
    3.24 +# PLOVER_V_SKIP: Don't echo anything for this command if V=0
    3.25 +PLOVER_V_SKIP = $(PLOVER_V_SKIP_$(V))
    3.26 +PLOVER_V_SKIP_ = $(PLOVER_V_SKIP_$(AM_DEFAULT_VERBOSITY))
    3.27 +PLOVER_V_SKIP_0 = @
    3.28 +
    3.29  .rc.$(OBJEXT):
    3.30 -	$(WINDRES) $< $@
    3.31 +	$(AM_V_GEN)$(WINDRES) $< $@
    3.32  
    3.33  resources.$(OBJEXT):	app-manager.ico app-manager.exe.manifest
    3.34  
    3.35  plover-applications%.pnm:	plover-applications.svg
    3.36 -	rsvg -w $* -h $* -f png $< temp.png
    3.37 -	pngtopnm temp.png | pnmquant 256 > $@
    3.38 -	$(RM) temp.png
    3.39 +	$(PLOVER_V_SKIP)rsvg -w $* -h $* -f png $< temp.png
    3.40 +	$(AM_V_GEN)pngtopnm temp.png | pnmquant -quiet 256 > $@
    3.41 +	$(PLOVER_V_SKIP)$(RM) temp.png
    3.42  
    3.43  plover-applications%.pgm:	plover-applications.svg
    3.44 -	rsvg -w $* -h $* -f png $< temp.png
    3.45 -	pngtopnm -alpha temp.png > $@
    3.46 -	$(RM) temp.png
    3.47 +	$(PLOVER_V_SKIP)rsvg -w $* -h $* -f png $< temp.png
    3.48 +	$(AM_V_GEN)pngtopnm -alpha temp.png > $@
    3.49 +	$(PLOVER_V_SKIP)$(RM) temp.png
    3.50  
    3.51  24x24/plover-applications.png:	plover-applications.svg
    3.52 -	mkdir -p 24x24
    3.53 -	rsvg -w 24 -h 24 -f png $< $@
    3.54 +	$(PLOVER_V_SKIP)mkdir -p 24x24
    3.55 +	$(AM_V_GEN)rsvg -w 24 -h 24 -f png $< $@
    3.56  
    3.57  48x48/plover-applications.png:	plover-applications.svg
    3.58 -	mkdir -p 48x48
    3.59 -	rsvg -w 48 -h 48 -f png $< $@
    3.60 +	$(PLOVER_V_SKIP)mkdir -p 48x48
    3.61 +	$(AM_V_GEN)rsvg -w 48 -h 48 -f png $< $@
    3.62  
    3.63  app-manager.ico:	plover-applications16.pnm plover-applications16.pgm \
    3.64  		plover-applications22.pnm plover-applications22.pgm \
    3.65  		plover-applications32.pnm plover-applications32.pgm \
    3.66  		plover-applications46.pnm plover-applications46.pgm
    3.67 -	ppmtowinicon -andpgms -output=$@ $^
    3.68 +	$(AM_V_GEN)ppmtowinicon -andpgms -output=$@ $^
    3.69  
    3.70  clean-local:
    3.71  	-rm -rf 24x24 48x48
     4.1 --- a/app-manager/app-manager.c	Fri Mar 23 20:29:50 2012 +0000
     4.2 +++ b/app-manager/app-manager.c	Sat Nov 15 19:04:45 2014 +0000
     4.3 @@ -19,13 +19,21 @@
     4.4  #include "config.h"
     4.5  #include <stdlib.h>
     4.6  #include <string.h>
     4.7 +#ifdef WIN32
     4.8 +#include <windows.h>
     4.9 +#endif	/* WIN32 */
    4.10 +#include <lua.h>
    4.11  #include <glib.h>
    4.12  #include <gio/gio.h>
    4.13  #include <gtk/gtk.h>
    4.14 -#include <plover-gtk/packageset.h>
    4.15 +#include <whelk/whelk.h>
    4.16 +#include <plover/packageset.h>
    4.17 +#include <plover-gtk/stockicons.h>
    4.18  #include "app-manager.h"
    4.19  #include "localmedia.h"
    4.20  
    4.21 +LUALIB_API int luaopen_posix(lua_State *L);
    4.22 +
    4.23  #define LOGO_NAME	"plover-applications"
    4.24  
    4.25  GtkBuilder *ui;
    4.26 @@ -103,6 +111,7 @@
    4.27      }
    4.28  }
    4.29  
    4.30 +#if 0
    4.31  /* Checks whether a loader for SVG files has been registered
    4.32   * with GdkPixbuf.
    4.33   */
    4.34 @@ -191,21 +200,61 @@
    4.35      icon_set=gtk_icon_factory_lookup_default(LOGO_NAME);
    4.36      gtk_window_set_default_icon_name(LOGO_NAME);
    4.37  }
    4.38 +#endif
    4.39 +
    4.40 +static void install_icons(void)
    4.41 +{
    4.42 +    GtkIconSet *icon_set;
    4.43 +    plover_icons_add_to_stock("apps",LOGO_NAME);
    4.44 +    icon_set=gtk_icon_factory_lookup_default(LOGO_NAME);
    4.45 +    gtk_window_set_default_icon_name(LOGO_NAME);
    4.46 +}
    4.47  
    4.48  int main(int argc,char **argv)
    4.49  {
    4.50      GError *err=0;
    4.51      GtkWidget *w;
    4.52      gchar *s,*contents;
    4.53 +    gchar *setup_base=NULL,*update_base=NULL;
    4.54      gsize len;
    4.55      PloverPackageSet *set;
    4.56 +    GSList *objects,*lnk;
    4.57 +    gboolean started;
    4.58      GOptionEntry options[]={
    4.59 +	{"setup",0,0,G_OPTION_ARG_FILENAME,&setup_base,
    4.60 +	  "Setup from installation media","path"},
    4.61 +	{"update",0,0,G_OPTION_ARG_FILENAME,&update_base,
    4.62 +	  "Update from upgrade media","path"},
    4.63  	{NULL}
    4.64      };
    4.65 +#ifdef WIN32
    4.66 +    /*
    4.67 +     * app-manager is normally a GUI application, but rpm scripts may well
    4.68 +     * call console applications and it looks ugly if console windows keep
    4.69 +     * popping up. Avoid this by allocating our own console and hiding it.
    4.70 +     * Note:
    4.71 +     *	- If app-manager is a console application (typically for debugging),
    4.72 +     *    then skip this step.
    4.73 +     *  - Call ShowWindow twice to negate special handling on first call.
    4.74 +     */
    4.75 +    if (!GetConsoleWindow())
    4.76 +    {
    4.77 +	AllocConsole();
    4.78 +	ShowWindow(GetConsoleWindow(),SW_HIDE);
    4.79 +	ShowWindow(GetConsoleWindow(),SW_HIDE);
    4.80 +    }
    4.81 +#endif
    4.82 +    razor_set_lua_loader("posix",luaopen_posix);
    4.83 +    razor_set_lua_loader("whelk",luaopen_whelk);
    4.84      if (!gtk_init_with_args(&argc,&argv,NULL,options,NULL,&err))
    4.85      {
    4.86 -	g_printerr("%s",err->message);
    4.87 -	exit(0);
    4.88 +	g_printerr("%s\n",err->message);
    4.89 +	exit(1);
    4.90 +    }
    4.91 +    if (setup_base && update_base)
    4.92 +    {
    4.93 +	g_printerr("--setup and --update are mutually exclusive\n");
    4.94 +	exit(1);
    4.95      }
    4.96  #ifdef WIN32
    4.97      prefix=g_win32_get_package_installation_directory_of_module(NULL);
    4.98 @@ -242,23 +291,45 @@
    4.99      gtk_builder_connect_signals(ui,NULL);
   4.100      gtk_link_button_set_uri_hook(show_uri,NULL,NULL);
   4.101      installed=GTK_TREE_MODEL(plover_package_store_new());
   4.102 -    set=plover_package_set_new_from_installed("",NULL);
   4.103 -    if (set)
   4.104 +    set=plover_package_set_new();
   4.105 +    (void)plover_package_set_open(set,"",TRUE,NULL);
   4.106 +    plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set);
   4.107 +    if (plover_package_set_get_no_details(set))
   4.108      {
   4.109 -	plover_package_store_add_set(PLOVER_PACKAGE_STORE(installed),set);
   4.110 -	if (plover_package_set_get_no_details(set))
   4.111 -	{
   4.112 -	    w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
   4.113 -	    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE);
   4.114 -	}
   4.115 +	w=GTK_WIDGET(gtk_builder_get_object(ui,"ViewFiles"));
   4.116 +	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),TRUE);
   4.117      }
   4.118      applications=plover_applications_model_new(installed);
   4.119      set_package_model(applications);
   4.120 -    gtk_main();
   4.121 -    g_object_unref(ui);
   4.122 +    if (setup_base)
   4.123 +	started=setup(set,setup_base);
   4.124 +    else if (update_base)
   4.125 +	started=update(set,update_base);
   4.126 +    else
   4.127 +    {
   4.128 +	w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
   4.129 +	gtk_widget_show(w);
   4.130 +	started=TRUE;
   4.131 +    }
   4.132 +    if (started)
   4.133 +	gtk_main();
   4.134 +    g_clear_object(&set);
   4.135 +    objects=gtk_builder_get_objects(ui);
   4.136 +    for(lnk=objects;lnk;lnk=lnk->next)
   4.137 +	if (GTK_IS_WIDGET(lnk->data) &&
   4.138 +	  gtk_widget_is_toplevel(GTK_WIDGET(lnk->data)))
   4.139 +	    gtk_widget_destroy(GTK_WIDGET(lnk->data));
   4.140 +    g_slist_free(objects);
   4.141 +    g_clear_object(&ui);
   4.142 +    g_clear_object(&installed);
   4.143 +    g_clear_object(&applications);
   4.144 +    g_clear_object(&location);
   4.145 +    g_clear_object(&local_media);
   4.146      if (relocations)
   4.147  	razor_relocations_destroy(relocations);
   4.148      g_free(prefix);
   4.149 +    g_free(setup_base);
   4.150 +    g_free(update_base);
   4.151      exit(0);
   4.152  }
   4.153  
   4.154 @@ -323,7 +394,7 @@
   4.155      {
   4.156  	show_busy_cursor(TRUE);
   4.157  	path=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
   4.158 -	set=plover_package_set_new_from_repository(path,relocations,&err);
   4.159 +	set=plover_package_set_new_from_yum(path,relocations,&err);
   4.160  	if (set)
   4.161  	{
   4.162  	    if (!location)
   4.163 @@ -399,7 +470,8 @@
   4.164      GtkWidget *w=GTK_WIDGET(gtk_builder_get_object(ui,"MainWindow"));
   4.165      gtk_show_about_dialog(GTK_WINDOW(w),"name",PACKAGE_NAME,
   4.166        "version",PACKAGE_VERSION,"comments","Application Manager",
   4.167 -      "copyright","Copyright © 2010 J. Ali Harlow","logo-icon-name",LOGO_NAME,
   4.168 +      "copyright","Copyright © 2010, 2014 J. Ali Harlow",
   4.169 +      "logo-icon-name",LOGO_NAME,
   4.170        NULL);
   4.171  }
   4.172  
     5.1 --- a/app-manager/app-manager.h	Fri Mar 23 20:29:50 2012 +0000
     5.2 +++ b/app-manager/app-manager.h	Sat Nov 15 19:04:45 2014 +0000
     5.3 @@ -1,9 +1,11 @@
     5.4  #include <razor.h>
     5.5  #include <gtk/gtk.h>
     5.6 -#include <plover-gtk/package.h>
     5.7 +#include <plover/package.h>
     5.8  
     5.9  extern GtkBuilder *ui;
    5.10  extern struct razor_relocations *relocations;
    5.11  GtkTreeModel *plover_applications_model_new(GtkTreeModel *installed);
    5.12  void set_package_model(GtkTreeModel *model);
    5.13  PloverPackage *get_active_package(void);
    5.14 +gboolean setup(PloverPackageSet *current,const char *base);
    5.15 +gboolean update(PloverPackageSet *current,const char *base);
     6.1 --- a/app-manager/app-manager.ui	Fri Mar 23 20:29:50 2012 +0000
     6.2 +++ b/app-manager/app-manager.ui	Sat Nov 15 19:04:45 2014 +0000
     6.3 @@ -1,9 +1,8 @@
     6.4  <?xml version="1.0"?>
     6.5  <interface>
     6.6    <requires lib="gtk+" version="2.16"/>
     6.7 -  <!-- interface-naming-policy toplevel-contextual -->
     6.8 +  <!-- interface-naming-policy project-wide -->
     6.9    <object class="GtkWindow" id="MainWindow">
    6.10 -    <property name="visible">True</property>
    6.11      <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    6.12      <property name="title" translatable="yes">Application Manager</property>
    6.13      <property name="default_width">600</property>
    6.14 @@ -368,7 +367,7 @@
    6.15                </packing>
    6.16              </child>
    6.17              <child>
    6.18 -              <object class="GtkAlignment" id="alignment2">
    6.19 +              <object class="GtkAlignment" id="alignment3">
    6.20                  <property name="visible">True</property>
    6.21                  <property name="left_padding">6</property>
    6.22                  <property name="right_padding">6</property>
     7.1 --- a/app-manager/applications.c	Fri Mar 23 20:29:50 2012 +0000
     7.2 +++ b/app-manager/applications.c	Sat Nov 15 19:04:45 2014 +0000
     7.3 @@ -25,6 +25,7 @@
     7.4  #include <glib.h>
     7.5  #include <gtk/gtk.h>
     7.6  #include <plover-gtk/packagestore.h>
     7.7 +#include <plover-gtk/packagefilestore.h>
     7.8  #include "app-manager.h"
     7.9  
    7.10  #ifdef WIN32
    7.11 @@ -63,7 +64,8 @@
    7.12      gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package,-1);
    7.13      if (package)
    7.14      {
    7.15 -	file_store=GTK_TREE_MODEL(plover_package_get_file_store(package));
    7.16 +	file_store=
    7.17 +	  GTK_TREE_MODEL(plover_package_file_store_new_from_package(package));
    7.18  	if (gtk_tree_model_get_iter_first(file_store,&fi))
    7.19  	{
    7.20  	    do
    7.21 @@ -94,6 +96,7 @@
    7.22  		g_free(name);
    7.23  	    } while(!visible && gtk_tree_model_iter_next(file_store,&fi));
    7.24  	}
    7.25 +	g_object_unref(file_store);
    7.26      }
    7.27      g_object_unref(package);
    7.28      return visible;
     8.1 --- a/app-manager/fetch.c	Fri Mar 23 20:29:50 2012 +0000
     8.2 +++ b/app-manager/fetch.c	Sat Nov 15 19:04:45 2014 +0000
     8.3 @@ -158,7 +158,7 @@
     8.4      const char *name;
     8.5      char *install_root;
     8.6      struct razor_set *set;
     8.7 -    struct razor_atomic *atomic;
     8.8 +    struct razor_error *error=NULL;
     8.9      struct razor_package *package;
    8.10      struct razor_package_iterator *pi;
    8.11      struct razor_file_iterator *fi;
    8.12 @@ -167,8 +167,7 @@
    8.13      install_root=getenv("RAZOR_ROOT");
    8.14      if (!install_root)
    8.15  	install_root="";
    8.16 -    atomic=razor_atomic_open("Query packages");
    8.17 -    set=razor_root_open_read_only(install_root,atomic);
    8.18 +    set=razor_root_open_read_only(install_root,&error);
    8.19      if (set)
    8.20      {
    8.21  	pi=razor_package_iterator_create(set);
    8.22 @@ -192,7 +191,8 @@
    8.23  	razor_package_iterator_destroy(pi);
    8.24  	razor_set_unref(set);
    8.25      }
    8.26 -    razor_atomic_destroy(atomic);
    8.27 +    if (error)
    8.28 +	razor_error_free(error);
    8.29      return retval;
    8.30  }
    8.31  
     9.1 --- a/app-manager/localmedia.c	Fri Mar 23 20:29:50 2012 +0000
     9.2 +++ b/app-manager/localmedia.c	Sat Nov 15 19:04:45 2014 +0000
     9.3 @@ -90,7 +90,7 @@
     9.4  #endif
     9.5      if (path)
     9.6      {
     9.7 -	set=plover_package_set_new_from_repository(path,relocations,NULL);
     9.8 +	set=plover_package_set_new_from_yum(path,relocations,NULL);
     9.9  	if (set)
    9.10  	{
    9.11  	    g_object_set_data(G_OBJECT(mount),"plover-local-media-set",set);
    10.1 --- a/app-manager/packagelist.c	Fri Mar 23 20:29:50 2012 +0000
    10.2 +++ b/app-manager/packagelist.c	Sat Nov 15 19:04:45 2014 +0000
    10.3 @@ -20,8 +20,8 @@
    10.4  #include <stdlib.h>
    10.5  #include <string.h>
    10.6  #include <gtk/gtk.h>
    10.7 -#include <plover-gtk/package.h>
    10.8 -#include <plover-gtk/packageset.h>
    10.9 +#include <plover/package.h>
   10.10 +#include <plover/packageset.h>
   10.11  #include <plover-gtk/packagestore.h>
   10.12  #include <plover-gtk/packagefilestore.h>
   10.13  #include "app-manager.h"
   10.14 @@ -36,6 +36,7 @@
   10.15      const char *text,*t;
   10.16      GtkWidget *w;
   10.17      GtkTextBuffer *buf;
   10.18 +    PloverPackageFileStore *store;
   10.19      buf=GTK_TEXT_BUFFER(gtk_builder_get_object(ui,"description"));
   10.20      if (package)
   10.21      {
   10.22 @@ -97,8 +98,9 @@
   10.23  	{
   10.24  	    gtk_widget_hide(w);
   10.25  	    w=GTK_WIDGET(gtk_builder_get_object(ui,"Files"));
   10.26 -	    gtk_tree_view_set_model(GTK_TREE_VIEW(w),
   10.27 -	      GTK_TREE_MODEL(plover_package_get_file_store(package)));
   10.28 +	    store=plover_package_file_store_new_from_package(package);
   10.29 +	    gtk_tree_view_set_model(GTK_TREE_VIEW(w),GTK_TREE_MODEL(store));
   10.30 +	    g_object_unref(store);
   10.31  	}
   10.32  	else
   10.33  	{
    11.1 --- a/app-manager/resources.rc.in	Fri Mar 23 20:29:50 2012 +0000
    11.2 +++ b/app-manager/resources.rc.in	Sat Nov 15 19:04:45 2014 +0000
    11.3 @@ -1,6 +1,8 @@
    11.4  #include <winver.h>
    11.5  #include <winuser.h>
    11.6  
    11.7 +#pragma code_page(65001)
    11.8 +
    11.9  MAINICON ICON "app-manager.ico"
   11.10  
   11.11  VS_VERSION_INFO VERSIONINFO
   11.12 @@ -31,3 +33,5 @@
   11.13  	    VALUE "Translation",0x809,0x4B0
   11.14  	}
   11.15      }
   11.16 +
   11.17 +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app-manager.exe.manifest"
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/app-manager/setup.c	Sat Nov 15 19:04:45 2014 +0000
    12.3 @@ -0,0 +1,88 @@
    12.4 +/*
    12.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    12.6 + *
    12.7 + * This program is free software; you can redistribute it and/or modify
    12.8 + * it under the terms of the GNU General Public License as published by
    12.9 + * the Free Software Foundation; either version 2 of the License, or
   12.10 + * (at your option) any later version.
   12.11 + *
   12.12 + * This program is distributed in the hope that it will be useful,
   12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.15 + * GNU General Public License for more details.
   12.16 + *
   12.17 + * You should have received a copy of the GNU General Public License along
   12.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   12.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   12.20 + */
   12.21 +
   12.22 +#include "config.h"
   12.23 +#include <stdlib.h>
   12.24 +#include <string.h>
   12.25 +#include <errno.h>
   12.26 +#include <glib.h>
   12.27 +#include <gio/gio.h>
   12.28 +#include <gtk/gtk.h>
   12.29 +#include <plover/plover.h>
   12.30 +#include <plover/transaction.h>
   12.31 +#include <plover/packageset.h>
   12.32 +#include <plover-gtk/transactionhelper.h>
   12.33 +#include "app-manager.h"
   12.34 +
   12.35 +gboolean setup(PloverPackageSet *installed,const char *base)
   12.36 +{
   12.37 +    gchar *s;
   12.38 +    const char *prefix;
   12.39 +    GError *error=NULL;
   12.40 +    static PloverTransactionHelper *helper=NULL;
   12.41 +    if (!helper)
   12.42 +    {
   12.43 +	helper=plover_transaction_helper_new(ui);
   12.44 +	plover_transaction_helper_set_installed(helper,installed);
   12.45 +	plover_transaction_helper_set_base(helper,base);
   12.46 +	prefix=plover_transaction_helper_get_prefix(helper,&error);
   12.47 +	if (error)
   12.48 +	    g_clear_error(&error);
   12.49 +	else
   12.50 +	{
   12.51 +	    s=g_strconcat(prefix?prefix:"","/var/log/setup",NULL);
   12.52 +	    plover_log_open(s);
   12.53 +	    g_free(s);
   12.54 +	}
   12.55 +	plover_transaction_helper_set_check_vendor(helper,TRUE);
   12.56 +	g_signal_connect(helper,"close",G_CALLBACK(gtk_main_quit),NULL);
   12.57 +    }
   12.58 +    if (!plover_transaction_helper_get_visible(helper))
   12.59 +    {
   12.60 +	if (!plover_transaction_helper_install_group(helper,"base",&error))
   12.61 +	{
   12.62 +	    if (g_error_matches(error,PLOVER_GENERAL_ERROR,
   12.63 +	      PLOVER_GENERAL_ERROR_NO_WORK))
   12.64 +	    {
   12.65 +		g_error_free(error);
   12.66 +		error=g_error_new_literal(PLOVER_GENERAL_ERROR,
   12.67 +		  PLOVER_GENERAL_ERROR_NO_WORK,
   12.68 +		  "All packages already installed");
   12.69 +		plover_transaction_helper_set_error(helper,error,
   12.70 +		  "Software installation");
   12.71 +	    }
   12.72 +	    else if (g_error_matches(error,PLOVER_GENERAL_ERROR,
   12.73 +	      PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET))
   12.74 +	    {
   12.75 +		g_error_free(error);
   12.76 +		error=g_error_new_literal(PLOVER_GENERAL_ERROR,
   12.77 +		  PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET,
   12.78 +		  "Software cannot be installed because of missing updates. "
   12.79 +		  "Installing all updates first should resolve this problem");
   12.80 +		plover_transaction_helper_set_error(helper,error,
   12.81 +		  "Software installation failed");
   12.82 +	    }
   12.83 +	    else
   12.84 +		plover_transaction_helper_set_error(helper,error,
   12.85 +		  "Software installation failed");
   12.86 +	    g_error_free(error);
   12.87 +	}
   12.88 +    }
   12.89 +    plover_transaction_helper_present(helper);
   12.90 +    return TRUE;
   12.91 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app-manager/update.c	Sat Nov 15 19:04:45 2014 +0000
    13.3 @@ -0,0 +1,89 @@
    13.4 +/*
    13.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    13.6 + *
    13.7 + * This program is free software; you can redistribute it and/or modify
    13.8 + * it under the terms of the GNU General Public License as published by
    13.9 + * the Free Software Foundation; either version 2 of the License, or
   13.10 + * (at your option) any later version.
   13.11 + *
   13.12 + * This program is distributed in the hope that it will be useful,
   13.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.15 + * GNU General Public License for more details.
   13.16 + *
   13.17 + * You should have received a copy of the GNU General Public License along
   13.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   13.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   13.20 + */
   13.21 +
   13.22 +#include "config.h"
   13.23 +#include <stdlib.h>
   13.24 +#include <string.h>
   13.25 +#include <errno.h>
   13.26 +#include <glib.h>
   13.27 +#include <gio/gio.h>
   13.28 +#include <gtk/gtk.h>
   13.29 +#include <plover/plover.h>
   13.30 +#include <plover/transaction.h>
   13.31 +#include <plover/packageset.h>
   13.32 +#include <plover-gtk/transactionhelper.h>
   13.33 +#include "app-manager.h"
   13.34 +
   13.35 +gboolean update(PloverPackageSet *installed,const char *base)
   13.36 +{
   13.37 +    gchar *s;
   13.38 +    const char *prefix;
   13.39 +    GError *error=NULL;
   13.40 +    static PloverTransactionHelper *helper=NULL;
   13.41 +    if (!helper)
   13.42 +    {
   13.43 +	helper=plover_transaction_helper_new(ui);
   13.44 +	plover_transaction_helper_set_installed(helper,installed);
   13.45 +	plover_transaction_helper_set_base(helper,base);
   13.46 +	prefix=plover_transaction_helper_get_prefix(helper,&error);
   13.47 +	if (error)
   13.48 +	    g_clear_error(&error);
   13.49 +	else
   13.50 +	{
   13.51 +	    s=g_strconcat(prefix?prefix:"","/var/log/update",NULL);
   13.52 +	    plover_log_open(s);
   13.53 +	    g_free(s);
   13.54 +	}
   13.55 +	plover_transaction_helper_set_check_vendor(helper,TRUE);
   13.56 +	g_signal_connect(helper,"close",G_CALLBACK(gtk_main_quit),NULL);
   13.57 +    }
   13.58 +    if (!plover_transaction_helper_get_visible(helper))
   13.59 +    {
   13.60 +	if (!plover_transaction_helper_update(helper,&error))
   13.61 +	{
   13.62 +	    if (g_error_matches(error,PLOVER_GENERAL_ERROR,
   13.63 +	      PLOVER_GENERAL_ERROR_NO_WORK))
   13.64 +	    {
   13.65 +		g_error_free(error);
   13.66 +		error=g_error_new_literal(PLOVER_GENERAL_ERROR,
   13.67 +		  PLOVER_GENERAL_ERROR_NO_WORK,
   13.68 +		  "All relevant updates already applied");
   13.69 +		plover_transaction_helper_set_error(helper,error,
   13.70 +		  "Software update");
   13.71 +	    }
   13.72 +	    else if (g_error_matches(error,PLOVER_GENERAL_ERROR,
   13.73 +	      PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET))
   13.74 +	    {
   13.75 +		g_error_free(error);
   13.76 +		error=g_error_new_literal(PLOVER_GENERAL_ERROR,
   13.77 +		  PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET,
   13.78 +		  "Updates cannot be applied because some earlier updates are "
   13.79 +		  "missing. Installing updates in sequence should resolve this "
   13.80 +		  "problem");
   13.81 +		plover_transaction_helper_set_error(helper,error,
   13.82 +		  "Software update failed");
   13.83 +	    }
   13.84 +	    else
   13.85 +		plover_transaction_helper_set_error(helper,error,
   13.86 +		  "Software update failed");
   13.87 +	    g_error_free(error);
   13.88 +	}
   13.89 +    }
   13.90 +    plover_transaction_helper_present(helper);
   13.91 +    return TRUE;
   13.92 +}
    14.1 --- a/configure.ac	Fri Mar 23 20:29:50 2012 +0000
    14.2 +++ b/configure.ac	Sat Nov 15 19:04:45 2014 +0000
    14.3 @@ -1,7 +1,7 @@
    14.4  #                                               -*- Autoconf -*-
    14.5  # Process this file with autoconf to produce a configure script.
    14.6  
    14.7 -AC_INIT([plover],[0.4.3],[ali@juiblex.co.uk])
    14.8 +AC_INIT([plover],[0.4.50],[ali@juiblex.co.uk])
    14.9  AC_PREREQ(2.59)
   14.10  AC_CONFIG_AUX_DIR([config])
   14.11  AC_CONFIG_SRCDIR([plover/plover.h])
   14.12 @@ -15,14 +15,18 @@
   14.13  setup/resources.rc
   14.14  update/Makefile
   14.15  update/resources.rc
   14.16 +pre-inst/Makefile
   14.17 +pre-inst/resources.rc
   14.18  app-manager/Makefile
   14.19  app-manager/resources.rc
   14.20  ])
   14.21  PLOVER_MSWIN_MANIFEST([setup/setup.exe.manifest:setup/manifest.xml.in
   14.22  update/update.exe.manifest:update/manifest.xml.in
   14.23 +pre-inst/pre-inst.exe.manifest:pre-inst/manifest.xml.in
   14.24  app-manager/app-manager.exe.manifest:app-manager/manifest.xml.in
   14.25  ])
   14.26  AM_INIT_AUTOMAKE(no-define)
   14.27 +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
   14.28  case $VERSION in
   14.29    *.*.*)
   14.30      AC_SUBST(PLOVER_MAJOR_VERSION,[[`echo $VERSION | sed 's/\..*//'`]])
   14.31 @@ -44,6 +48,15 @@
   14.32  AC_CANONICAL_HOST
   14.33  AC_SUBST(HOST_OS,$host_os)
   14.34  AC_SUBST(HOST_CPU,$host_cpu)
   14.35 +case $host_os in
   14.36 +    mingw*)
   14.37 +	host_mingw="yes"
   14.38 +	;;
   14.39 +    *)
   14.40 +	host_mingw=""
   14.41 +	;;
   14.42 +esac
   14.43 +AM_CONDITIONAL(PLOVER_MINGW,[test -n "$host_mingw"])
   14.44  
   14.45  # libtool versioning for libplover. For a release one of the following
   14.46  # must apply:
   14.47 @@ -54,7 +67,7 @@
   14.48  #   increment CURRENT and set AGE and REVISION to 0.
   14.49  # - If the interface is the same as the previous version, increment REVISION.
   14.50  #
   14.51 -lt_current=2
   14.52 +lt_current=3
   14.53  lt_revision=0
   14.54  lt_age=0
   14.55  LIBPLOVER_LT_VERSION_INFO="$lt_current:$lt_revision:$lt_age"
   14.56 @@ -93,32 +106,44 @@
   14.57  ##################################################
   14.58  # Checks for libraries.
   14.59  ##################################################
   14.60 +PKG_CHECK_MODULES(WHELK,[whelk])
   14.61  PKG_CHECK_MODULES(RAZOR,[razor >= 0.5.4],[:],[RAZOR_LIBS=-lrazor])
   14.62  PKG_CHECK_MODULES(EXPAT,[expat],[:],[EXPAT_LIBS=-lexpat])
   14.63  PKG_CHECK_MODULES(ZLIB,[zlib],[:],[ZLIB_LIBS=-lz])
   14.64  PKG_CHECK_MODULES(GIO,[gio-2.0])
   14.65  PKG_CHECK_MODULES(GTK,[gtk+-2.0])
   14.66  PKG_CHECK_MODULES(GMODULE_EXPORT,[gmodule-export-2.0])
   14.67 -LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS"
   14.68 -LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS"
   14.69 +LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS $GIO_CFLAGS"
   14.70 +LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS $GIO_LIBS"
   14.71  AC_SUBST(LIBPLOVER_CFLAGS)
   14.72  AC_SUBST(LIBPLOVER_LIBS)
   14.73  PLOVER_GTK_CFLAGS="$GTK_CFLAGS $RAZOR_CFLAGS"
   14.74  PLOVER_GTK_LIBS="$GTK_LIBS $RAZOR_LIBS"
   14.75  AC_SUBST(PLOVER_GTK_CFLAGS)
   14.76  AC_SUBST(PLOVER_GTK_LIBS)
   14.77 -GUI_CFLAGS="$GMODULE_EXPORT_CFLAGS $GIO_CFLAGS $PLOVER_GTK_CFLAGS $LIBPLOVER_CFLAGS"
   14.78 -GUI_LIBS="$GMODULE_EXPORT_LIBS $GIO_LIBS $PLOVER_GTK_LIBS $LIBPLOVER_LIBS"
   14.79 +save_LIBS="$LIBS"
   14.80 +AC_SEARCH_LIBS([crypt],[crypt])
   14.81 +GUI_CFLAGS="$GMODULE_EXPORT_CFLAGS $WHELK_CFLAGS $PLOVER_GTK_CFLAGS \
   14.82 +  $LIBPLOVER_CFLAGS"
   14.83 +GUI_LIBS="-llua-posix $GMODULE_EXPORT_LIBS $WHELK_LIBS $PLOVER_GTK_LIBS \
   14.84 +  $LIBPLOVER_LIBS $LIBS"
   14.85 +LIBS="$save_LIBS"
   14.86  AC_SUBST(GUI_CFLAGS)
   14.87  AC_SUBST(GUI_LIBS)
   14.88  save_PKG_CONFIG="$PKG_CONFIG"
   14.89  PKG_CONFIG="$PKG_CONFIG --static"
   14.90 -PKG_CHECK_MODULES(SETUP,[whelk])
   14.91 +PKG_CHECK_MODULES(SETUP,[whelk razor >= 0.5.4 expat zlib gio-2.0])
   14.92 +if test -n "$host_mingw"; then
   14.93 +    # Hack: -liconv is required for mingw. This probably stems from our use of
   14.94 +    # libiconv rather than win-iconv that Fedora uses, but should be addressed
   14.95 +    # somewhere in the stack below us.
   14.96 +    SETUP_LIBS="$SETUP_LIBS -liconv"
   14.97 +fi
   14.98  PKG_CONFIG="$save_PKG_CONFIG"
   14.99  save_LIBS="$LIBS"
  14.100  AC_SEARCH_LIBS([crypt],[crypt])
  14.101 -SETUP_LIBS="-llua-posix $SETUP_LIBS $RAZOR_LIBS $LIBS"
  14.102 -SETUP_CFLAGS="$SETUP_CFLAGS $RAZOR_CFLAGS"
  14.103 +SETUP_LIBS="-llua-posix $SETUP_LIBS $LIBS"
  14.104 +SETUP_CFLAGS="$SETUP_CFLAGS"
  14.105  AC_SUBST(SETUP_LIBS)
  14.106  AC_SUBST(SETUP_CFLAGS)
  14.107  LIBS="$save_LIBS"
  14.108 @@ -139,7 +164,7 @@
  14.109  ##################################################
  14.110  # Checks for library functions.
  14.111  ##################################################
  14.112 -AC_CHECK_FUNCS_ONCE([fchdir])
  14.113 +AC_CHECK_FUNCS_ONCE([fchdir fpathconf dirfd])
  14.114  
  14.115  ##################################################
  14.116  # Checks for processor independent files.
    15.1 --- a/plover-gtk/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
    15.2 +++ b/plover-gtk/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
    15.3 @@ -1,15 +1,19 @@
    15.4 -AM_CFLAGS=-g $(PLOVER_GTK_CFLAGS)
    15.5 +AM_CFLAGS=-g $(PLOVER_GTK_CFLAGS) -DPLOVER_DATADIR=\""$(pkgdatadir)"\"
    15.6  LIBS=../plover/libplover.la $(PLOVER_GTK_LIBS)
    15.7  INCLUDES=-I$(top_srcdir)
    15.8  AM_LDFLAGS=-no-undefined -version-info $(PLOVER_GTK_LT_VERSION_INFO)
    15.9  
   15.10 -pkginclude_HEADERS=error.h package.h packageset.h packagestore.h \
   15.11 -		packagefilestore.h
   15.12 +uidir=$(pkgdatadir)
   15.13 +ui_DATA=software-installation.ui
   15.14 +
   15.15 +pkginclude_HEADERS=\
   15.16 +	transactionhelper.h packagestore.h packagefilestore.h stockicons.h
   15.17  
   15.18  lib_LTLIBRARIES=libplover-gtk.la
   15.19  libplover_gtk_la_SOURCES=$(pkginclude_HEADERS) \
   15.20 -		error.c package.c packageset.c packagestore.c \
   15.21 -		packagefilestore.c
   15.22 +	transactionhelper.c packagestore.c packagefilestore.c stockicons.c
   15.23  
   15.24  pkgconfigdir=$(libdir)/pkgconfig
   15.25  pkgconfig_DATA=plover-gtk.pc
   15.26 +
   15.27 +EXTRA_DIST=software-installation.ui
    16.1 --- a/plover-gtk/error.c	Fri Mar 23 20:29:50 2012 +0000
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,30 +0,0 @@
    16.4 -/*
    16.5 - * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
    16.6 - *
    16.7 - * This program is free software; you can redistribute it and/or modify
    16.8 - * it under the terms of the GNU General Public License as published by
    16.9 - * the Free Software Foundation; either version 2 of the License, or
   16.10 - * (at your option) any later version.
   16.11 - *
   16.12 - * This program is distributed in the hope that it will be useful,
   16.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.15 - * GNU General Public License for more details.
   16.16 - *
   16.17 - * You should have received a copy of the GNU General Public License along
   16.18 - * with this program; if not, write to the Free Software Foundation, Inc.,
   16.19 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   16.20 - */
   16.21 -
   16.22 -#include "config.h"
   16.23 -#include <stdlib.h>
   16.24 -#include <glib.h>
   16.25 -
   16.26 -GQuark plover_razor_error_quark(void)
   16.27 -{
   16.28 -    static GQuark quark=0;
   16.29 -    if (!quark)
   16.30 -	quark=g_quark_from_static_string("plover-razor-error-quark");
   16.31 -    return quark;
   16.32 -}
   16.33 -
    17.1 --- a/plover-gtk/error.h	Fri Mar 23 20:29:50 2012 +0000
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,12 +0,0 @@
    17.4 -#ifndef __PLOVER_ERROR_H__
    17.5 -#define __PLOVER_ERROR_H__
    17.6 -
    17.7 -#define PLOVER_RAZOR_ERROR	plover_razor_error_quark()
    17.8 -
    17.9 -typedef enum {
   17.10 -    PLOVER_RAZOR_ERROR_FAILED
   17.11 -} PloverRazorError;
   17.12 -
   17.13 -GQuark plover_razor_error_quark(void);
   17.14 -
   17.15 -#endif /* __PLOVER_ERROR_H__ */
    18.1 --- a/plover-gtk/package.c	Fri Mar 23 20:29:50 2012 +0000
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,180 +0,0 @@
    18.4 -/*
    18.5 - * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
    18.6 - *
    18.7 - * This program is free software; you can redistribute it and/or modify
    18.8 - * it under the terms of the GNU General Public License as published by
    18.9 - * the Free Software Foundation; either version 2 of the License, or
   18.10 - * (at your option) any later version.
   18.11 - *
   18.12 - * This program is distributed in the hope that it will be useful,
   18.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.15 - * GNU General Public License for more details.
   18.16 - *
   18.17 - * You should have received a copy of the GNU General Public License along
   18.18 - * with this program; if not, write to the Free Software Foundation, Inc.,
   18.19 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   18.20 - */
   18.21 -
   18.22 -#include "config.h"
   18.23 -#include <stdlib.h>
   18.24 -#include <string.h>
   18.25 -#include <glib-object.h>
   18.26 -#include <gtk/gtk.h>
   18.27 -#include <razor.h>
   18.28 -#include "plover-gtk/package.h"
   18.29 -
   18.30 -G_DEFINE_TYPE(PloverPackage,plover_package,G_TYPE_OBJECT);
   18.31 -
   18.32 -typedef struct _PloverPackagePrivate {
   18.33 -    struct razor_set *set;
   18.34 -    struct razor_package *pkg;
   18.35 -    PloverPackageFileStore *file_store;
   18.36 -} PloverPackagePrivate;
   18.37 -
   18.38 -#define PLOVER_PACKAGE_GET_PRIVATE(obj)\
   18.39 -				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
   18.40 -				  PLOVER_TYPE_PACKAGE,PloverPackagePrivate)
   18.41 -
   18.42 -enum {
   18.43 -    CHANGED=0,
   18.44 -    N_SIGNALS
   18.45 -};
   18.46 -
   18.47 -static guint signals[N_SIGNALS];
   18.48 -
   18.49 -static void plover_package_dispose(GObject *obj)
   18.50 -{
   18.51 -    PloverPackagePrivate *priv=PLOVER_PACKAGE_GET_PRIVATE(obj);
   18.52 -    if (priv->file_store)
   18.53 -    {
   18.54 -	g_object_unref(priv->file_store);
   18.55 -	priv->file_store=NULL;
   18.56 -    }
   18.57 -    if (G_OBJECT_CLASS(plover_package_parent_class)->dispose)
   18.58 -	G_OBJECT_CLASS(plover_package_parent_class)->dispose(obj);
   18.59 -}
   18.60 -
   18.61 -static void plover_package_class_init(PloverPackageClass *klass)
   18.62 -{
   18.63 -    GObjectClass *oclass=G_OBJECT_CLASS(klass);
   18.64 -    oclass->dispose=plover_package_dispose;
   18.65 -    g_type_class_add_private(klass,sizeof(PloverPackagePrivate));
   18.66 -    signals[CHANGED]=g_signal_newv("changed",
   18.67 -      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
   18.68 -      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
   18.69 -}
   18.70 -
   18.71 -static void plover_package_init(PloverPackage *package)
   18.72 -{
   18.73 -}
   18.74 -
   18.75 -PloverPackage *plover_package_new(struct razor_set *set,
   18.76 -  struct razor_package *pkg)
   18.77 -{
   18.78 -    PloverPackage *package;
   18.79 -    PloverPackagePrivate *priv;
   18.80 -    package=g_object_new(PLOVER_TYPE_PACKAGE,NULL);
   18.81 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   18.82 -    priv->set=set;
   18.83 -    priv->pkg=pkg;
   18.84 -    return package;
   18.85 -}
   18.86 -
   18.87 -const char *plover_package_get_name(PloverPackage *package)
   18.88 -{
   18.89 -    PloverPackagePrivate *priv;
   18.90 -    const char *name=NULL;
   18.91 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   18.92 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   18.93 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_NAME,&name,
   18.94 -      RAZOR_DETAIL_LAST);
   18.95 -    return name;
   18.96 -}
   18.97 -
   18.98 -const char *plover_package_get_summary(PloverPackage *package)
   18.99 -{
  18.100 -    PloverPackagePrivate *priv;
  18.101 -    const char *summary=NULL;
  18.102 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.103 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.104 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_SUMMARY,&summary,
  18.105 -      RAZOR_DETAIL_LAST);
  18.106 -    return summary;
  18.107 -}
  18.108 -
  18.109 -const char *plover_package_get_version(PloverPackage *package)
  18.110 -{
  18.111 -    PloverPackagePrivate *priv;
  18.112 -    const char *version=NULL;
  18.113 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.114 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.115 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_VERSION,&version,
  18.116 -      RAZOR_DETAIL_LAST);
  18.117 -    return version;
  18.118 -}
  18.119 -
  18.120 -const char *plover_package_get_license(PloverPackage *package)
  18.121 -{
  18.122 -    PloverPackagePrivate *priv;
  18.123 -    const char *license=NULL;
  18.124 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.125 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.126 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_LICENSE,&license,
  18.127 -      RAZOR_DETAIL_LAST);
  18.128 -    return license;
  18.129 -}
  18.130 -
  18.131 -const char *plover_package_get_arch(PloverPackage *package)
  18.132 -{
  18.133 -    PloverPackagePrivate *priv;
  18.134 -    const char *arch=NULL;
  18.135 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.136 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.137 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_ARCH,&arch,
  18.138 -      RAZOR_DETAIL_LAST);
  18.139 -    return arch;
  18.140 -}
  18.141 -
  18.142 -const char *plover_package_get_description(PloverPackage *package)
  18.143 -{
  18.144 -    PloverPackagePrivate *priv;
  18.145 -    const char *description=NULL;
  18.146 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.147 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.148 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_DESCRIPTION,
  18.149 -      &description,RAZOR_DETAIL_LAST);
  18.150 -    return description;
  18.151 -}
  18.152 -
  18.153 -const char *plover_package_get_URL(PloverPackage *package)
  18.154 -{
  18.155 -    PloverPackagePrivate *priv;
  18.156 -    const char *URL=NULL;
  18.157 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.158 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.159 -    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_URL,&URL,
  18.160 -      RAZOR_DETAIL_LAST);
  18.161 -    return URL;
  18.162 -}
  18.163 -
  18.164 -GdkPixbuf *plover_package_get_icon(PloverPackage *package)
  18.165 -{
  18.166 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.167 -    return NULL;
  18.168 -}
  18.169 -
  18.170 -PloverPackageFileStore *plover_package_get_file_store(PloverPackage *package)
  18.171 -{
  18.172 -    PloverPackagePrivate *priv;
  18.173 -    struct razor_file_iterator *iter;
  18.174 -    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  18.175 -    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  18.176 -    if (!priv->file_store)
  18.177 -    {
  18.178 -	iter=razor_file_iterator_create(priv->set,priv->pkg,0);
  18.179 -	priv->file_store=plover_package_file_store_new(iter);
  18.180 -	razor_file_iterator_destroy(iter);
  18.181 -    }
  18.182 -    return priv->file_store;
  18.183 -}
    19.1 --- a/plover-gtk/package.h	Fri Mar 23 20:29:50 2012 +0000
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,50 +0,0 @@
    19.4 -#ifndef __PLOVER_PACKAGE_H__
    19.5 -#define __PLOVER_PACKAGE_H__
    19.6 -
    19.7 -#include <razor.h>
    19.8 -#include <glib-object.h>
    19.9 -#include <gdk-pixbuf/gdk-pixbuf.h>
   19.10 -#include <plover-gtk/packageset.h>
   19.11 -#include <plover-gtk/packagefilestore.h>
   19.12 -
   19.13 -G_BEGIN_DECLS
   19.14 -
   19.15 -#define PLOVER_TYPE_PACKAGE	plover_package_get_type()
   19.16 -#define PLOVER_PACKAGE(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   19.17 -				  PLOVER_TYPE_PACKAGE,PloverPackage)
   19.18 -#define PLOVER_PACKAGE_CLASS(klass)\
   19.19 -				G_TYPE_CHECK_CLASS_CAST(klass,\
   19.20 -				  PLOVER_TYPE_PACKAGE,PloverPackageClass)
   19.21 -#define PLOVER_IS_PACKAGE(obj)	G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   19.22 -				  PLOVER_TYPE_PACKAGE)
   19.23 -#define PLOVER_IS_PACKAGE_CLASS(klass)\
   19.24 -				G_TYPE_CHECK_CLASS_TYPE(obj,\
   19.25 -				  PLOVER_TYPE_PACKAGE)
   19.26 -#define PLOVER_PACKAGE_GET_CLASS(obj)\
   19.27 -				G_TYPE_INSTANCE_GET_CLASS(obj,\
   19.28 -				  PLOVER_TYPE_PACKAGE,PloverPackageClass)
   19.29 -
   19.30 -typedef struct _PloverPackage {
   19.31 -    GObject parent_instance;
   19.32 -} PloverPackage;
   19.33 -
   19.34 -typedef struct _PloverPackageClass {
   19.35 -    GObjectClass parent_class;
   19.36 -} PloverPackageClass;
   19.37 -
   19.38 -GType plover_package_get_type(void) G_GNUC_CONST;
   19.39 -PloverPackage *plover_package_new(struct razor_set *set,
   19.40 -  struct razor_package *pkg);
   19.41 -const char *plover_package_get_name(PloverPackage *package);
   19.42 -const char *plover_package_get_summary(PloverPackage *package);
   19.43 -const char *plover_package_get_version(PloverPackage *package);
   19.44 -const char *plover_package_get_license(PloverPackage *package);
   19.45 -const char *plover_package_get_arch(PloverPackage *package);
   19.46 -const char *plover_package_get_description(PloverPackage *package);
   19.47 -const char *plover_package_get_URL(PloverPackage *package);
   19.48 -GdkPixbuf *plover_package_get_icon(PloverPackage *package);
   19.49 -PloverPackageFileStore *plover_package_get_file_store(PloverPackage *package);
   19.50 -
   19.51 -G_END_DECLS
   19.52 -
   19.53 -#endif /* __PLOVER_PACKAGE_H__ */
    20.1 --- a/plover-gtk/packagefilestore.c	Fri Mar 23 20:29:50 2012 +0000
    20.2 +++ b/plover-gtk/packagefilestore.c	Sat Nov 15 19:04:45 2014 +0000
    20.3 @@ -257,3 +257,15 @@
    20.4      gtk_tree_path_free(path);
    20.5      return store;
    20.6  }
    20.7 +
    20.8 +PloverPackageFileStore *
    20.9 +  plover_package_file_store_new_from_package(PloverPackage *package)
   20.10 +{
   20.11 +    PloverPackageFileStore *store;
   20.12 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   20.13 +    struct razor_file_iterator *iter;
   20.14 +    iter=plover_package_file_iterator_create(package,FALSE);
   20.15 +    store=GTK_TREE_MODEL(plover_package_file_store_new(iter));
   20.16 +    razor_file_iterator_destroy(iter);
   20.17 +    return store;
   20.18 +}
    21.1 --- a/plover-gtk/packagefilestore.h	Fri Mar 23 20:29:50 2012 +0000
    21.2 +++ b/plover-gtk/packagefilestore.h	Sat Nov 15 19:04:45 2014 +0000
    21.3 @@ -2,6 +2,7 @@
    21.4  #define __PLOVER_PACKAGE_FILE_STORE_H__
    21.5  
    21.6  #include <glib-object.h>
    21.7 +#include <plover/package.h>
    21.8  #include <razor.h>
    21.9  
   21.10  G_BEGIN_DECLS
   21.11 @@ -44,6 +45,8 @@
   21.12  GType plover_package_file_store_get_type(void) G_GNUC_CONST;
   21.13  PloverPackageFileStore *
   21.14    plover_package_file_store_new(struct razor_file_iterator *files);
   21.15 +PloverPackageFileStore *
   21.16 +  plover_package_file_store_new_from_package(PloverPackage *package);
   21.17  
   21.18  G_END_DECLS
   21.19  
    22.1 --- a/plover-gtk/packageset.c	Fri Mar 23 20:29:50 2012 +0000
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,259 +0,0 @@
    22.4 -/*
    22.5 - * Copyright (C) 2010-2012  J. Ali Harlow <ali@juiblex.co.uk>
    22.6 - *
    22.7 - * This program is free software; you can redistribute it and/or modify
    22.8 - * it under the terms of the GNU General Public License as published by
    22.9 - * the Free Software Foundation; either version 2 of the License, or
   22.10 - * (at your option) any later version.
   22.11 - *
   22.12 - * This program is distributed in the hope that it will be useful,
   22.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.15 - * GNU General Public License for more details.
   22.16 - *
   22.17 - * You should have received a copy of the GNU General Public License along
   22.18 - * with this program; if not, write to the Free Software Foundation, Inc.,
   22.19 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   22.20 - */
   22.21 -
   22.22 -#include "config.h"
   22.23 -#include <stdlib.h>
   22.24 -#include <string.h>
   22.25 -#include <fcntl.h>
   22.26 -#include <errno.h>
   22.27 -#include <unistd.h>
   22.28 -#include <glib-object.h>
   22.29 -#include <razor.h>
   22.30 -#include "plover/plover.h"
   22.31 -#include "plover-gtk/error.h"
   22.32 -#include "plover-gtk/packageset.h"
   22.33 -#include "plover-gtk/package.h"
   22.34 -
   22.35 -G_DEFINE_TYPE(PloverPackageSet,plover_package_set,G_TYPE_OBJECT);
   22.36 -
   22.37 -typedef struct _PloverPackageSetPrivate {
   22.38 -    struct razor_root *root;
   22.39 -    struct razor_set *set;
   22.40 -    GSList *packages;
   22.41 -    int no_details;
   22.42 -} PloverPackageSetPrivate;
   22.43 -
   22.44 -#define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
   22.45 -				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
   22.46 -				  PLOVER_TYPE_PACKAGE_SET,\
   22.47 -				  PloverPackageSetPrivate)
   22.48 -
   22.49 -enum {
   22.50 -    CHANGED=0,
   22.51 -    N_SIGNALS
   22.52 -};
   22.53 -
   22.54 -static guint signals[N_SIGNALS];
   22.55 -
   22.56 -static void plover_package_set_finalize(GObject *obj)
   22.57 -{
   22.58 -    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
   22.59 -    if (priv->root)
   22.60 -	razor_root_close(priv->root);
   22.61 -    if (G_OBJECT_CLASS(plover_package_set_parent_class)->finalize)
   22.62 -	G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj);
   22.63 -}
   22.64 -
   22.65 -static void plover_package_set_dispose(GObject *obj)
   22.66 -{
   22.67 -    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
   22.68 -    if (priv->set)
   22.69 -    {
   22.70 -	razor_set_unref(priv->set);
   22.71 -	priv->set=NULL;
   22.72 -    }
   22.73 -    if (G_OBJECT_CLASS(plover_package_set_parent_class)->dispose)
   22.74 -	G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj);
   22.75 -}
   22.76 -
   22.77 -static void plover_package_set_class_init(PloverPackageSetClass *klass)
   22.78 -{
   22.79 -    GObjectClass *oclass=G_OBJECT_CLASS(klass);
   22.80 -    oclass->finalize=plover_package_set_finalize;
   22.81 -    oclass->dispose=plover_package_set_dispose;
   22.82 -    g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate));
   22.83 -    signals[CHANGED]=g_signal_newv("changed",
   22.84 -      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
   22.85 -      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
   22.86 -}
   22.87 -
   22.88 -static void plover_package_set_init(PloverPackageSet *set)
   22.89 -{
   22.90 -    PloverPackageSetPrivate *priv;
   22.91 -    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   22.92 -    priv->no_details=-1;
   22.93 -}
   22.94 -
   22.95 -PloverPackageSet *plover_package_set_new(void)
   22.96 -{
   22.97 -    return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL);
   22.98 -}
   22.99 -
  22.100 -PloverPackageSet *plover_package_set_new_from_installed(const char *root,
  22.101 -  GError **err)
  22.102 -{
  22.103 -    PloverPackageSet *set;
  22.104 -    PloverPackageSetPrivate *priv;
  22.105 -    struct razor_error *error=NULL;
  22.106 -    set=plover_package_set_new();
  22.107 -    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  22.108 -    priv->root=razor_root_open(root,&error);
  22.109 -    if (!priv->root)
  22.110 -    {
  22.111 -	g_set_error_literal(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
  22.112 -	  razor_error_get_msg(error));
  22.113 -	razor_error_free(error);
  22.114 -	g_object_unref(set);
  22.115 -	return NULL;
  22.116 -    }
  22.117 -    priv->set=razor_set_ref(razor_root_get_system_set(priv->root));
  22.118 -    if (!priv->set)
  22.119 -    {
  22.120 -	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
  22.121 -	  "Failed to get system set from %s",root);
  22.122 -	g_object_unref(set);
  22.123 -	return NULL;
  22.124 -    }
  22.125 -    return set;
  22.126 -}
  22.127 -
  22.128 -PloverPackageSet *plover_package_set_new_from_repository(const char *base,
  22.129 -  struct razor_relocations *relocations,GError **err)
  22.130 -{
  22.131 -#if HAVE_FCHDIR
  22.132 -    int fd;
  22.133 -#else
  22.134 -    size_t wd_len;
  22.135 -    char *wd;
  22.136 -#endif
  22.137 -    gchar *s;
  22.138 -    struct razor_set *reloc;
  22.139 -    struct razor_error *error=NULL;
  22.140 -    PloverPackageSet *set;
  22.141 -    PloverPackageSetPrivate *priv;
  22.142 -    set=plover_package_set_new();
  22.143 -    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  22.144 -#if HAVE_FCHDIR
  22.145 -    fd=open(".",O_RDONLY);
  22.146 -#else
  22.147 -    wd_len=32;
  22.148 -    wd=malloc(wd_len);
  22.149 -    while (!getcwd(wd,wd_len) && errno==ERANGE)
  22.150 -    {
  22.151 -	free(wd);
  22.152 -	wd_len*=2;
  22.153 -	wd=malloc(wd_len);
  22.154 -    }
  22.155 -#endif
  22.156 -    s=g_build_filename(base,"repodata",NULL);
  22.157 -    if (chdir(s)<0)
  22.158 -    {
  22.159 -	g_set_error(err,G_FILE_ERROR,g_file_error_from_errno(errno),
  22.160 -	  "%s: %s",s,g_strerror(errno));
  22.161 -	g_object_unref(set);
  22.162 -#if HAVE_FCHDIR
  22.163 -	close(fd);
  22.164 -#else
  22.165 -	free(wd);
  22.166 -#endif
  22.167 -	return NULL;
  22.168 -    }
  22.169 -    g_free(s);
  22.170 -    priv->set=plover_razor_set_create_from_yum("..");
  22.171 -#if HAVE_FCHDIR
  22.172 -    (void)fchdir(fd);
  22.173 -    close(fd);
  22.174 -#else
  22.175 -    chdir(wd);
  22.176 -    free(wd);
  22.177 -#endif
  22.178 -    if (priv->set && relocations)
  22.179 -    {
  22.180 -	reloc=plover_relocate_packages(priv->set,base,relocations,&error);
  22.181 -	if (!reloc)
  22.182 -	{
  22.183 -	    g_set_error_literal(err,PLOVER_RAZOR_ERROR,
  22.184 -	      PLOVER_RAZOR_ERROR_FAILED,razor_error_get_msg(error));
  22.185 -	    razor_error_free(error);
  22.186 -	    g_object_unref(set);
  22.187 -	    return NULL;
  22.188 -	}
  22.189 -	razor_set_unref(priv->set);
  22.190 -	priv->set=reloc;
  22.191 -    }
  22.192 -    if (!priv->set)
  22.193 -    {
  22.194 -	g_set_error(err,PLOVER_RAZOR_ERROR,PLOVER_RAZOR_ERROR_FAILED,
  22.195 -	  "Failed to create package set from repository %s",base);
  22.196 -	g_object_unref(set);
  22.197 -	return NULL;
  22.198 -    }
  22.199 -    return set;
  22.200 -}
  22.201 -
  22.202 -GSList *plover_package_set_get_packages(PloverPackageSet *set)
  22.203 -{
  22.204 -    struct razor_package_iterator *iter;
  22.205 -    struct razor_package *pkg;
  22.206 -    PloverPackageSetPrivate *priv;
  22.207 -    PloverPackage *package;
  22.208 -    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  22.209 -    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  22.210 -    if (priv->set && !priv->packages)
  22.211 -    {
  22.212 -	iter=razor_package_iterator_create(priv->set);
  22.213 -	while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST))
  22.214 -	{
  22.215 -	    package=plover_package_new(priv->set,pkg);
  22.216 -	    priv->packages=g_slist_prepend(priv->packages,package);
  22.217 -	}
  22.218 -	razor_package_iterator_destroy(iter);
  22.219 -    }
  22.220 -    return priv->packages;
  22.221 -}
  22.222 -
  22.223 -/*
  22.224 - * Some versions of razor have a bug which causes all detail strings
  22.225 - * to be discarded. If such a version of razor is used to install or
  22.226 - * update a package, then all the detail strings for the installed
  22.227 - * set will be lost. This function tests for this condition and can
  22.228 - * be used to present something more useful than blank details.
  22.229 - */
  22.230 -
  22.231 -gboolean plover_package_set_get_no_details(PloverPackageSet *set)
  22.232 -{
  22.233 -    PloverPackageSetPrivate *priv;
  22.234 -    PloverPackage *package;
  22.235 -    GSList *packages,*link;
  22.236 -    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  22.237 -    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  22.238 -    if (priv->no_details<0)
  22.239 -    {
  22.240 -	packages=plover_package_set_get_packages(set);
  22.241 -	if (packages)
  22.242 -	{
  22.243 -	    priv->no_details=0;
  22.244 -	    for(link=packages;link;link=link->next)
  22.245 -	    {
  22.246 -		package=link->data;
  22.247 -		priv->no_details+=2;
  22.248 -		if (*plover_package_get_summary(package))
  22.249 -		    priv->no_details--;
  22.250 -		if (*plover_package_get_license(package))
  22.251 -		    priv->no_details--;
  22.252 -		if (*plover_package_get_description(package))
  22.253 -		    priv->no_details--;
  22.254 -		if (*plover_package_get_URL(package))
  22.255 -		    priv->no_details--;
  22.256 -	    }
  22.257 -	    if (priv->no_details<0)	/* More than 50% of strings present */
  22.258 -		priv->no_details=0;
  22.259 -	}
  22.260 -    }
  22.261 -    return priv->no_details>0;
  22.262 -}
    23.1 --- a/plover-gtk/packageset.h	Fri Mar 23 20:29:50 2012 +0000
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,46 +0,0 @@
    23.4 -#ifndef __PLOVER_PACKAGE_SET_H__
    23.5 -#define __PLOVER_PACKAGE_SET_H__
    23.6 -
    23.7 -#include <razor.h>
    23.8 -#include <glib-object.h>
    23.9 -
   23.10 -G_BEGIN_DECLS
   23.11 -
   23.12 -#define PLOVER_TYPE_PACKAGE_SET	plover_package_set_get_type()
   23.13 -#define PLOVER_PACKAGE_SET(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   23.14 -				  PLOVER_TYPE_PACKAGE_SET,PloverPackageSet)
   23.15 -#define PLOVER_PACKAGE_SET_CLASS(klass)\
   23.16 -				G_TYPE_CHECK_CLASS_CAST(klass,\
   23.17 -				  PLOVER_TYPE_PACKAGE_SET,\
   23.18 -				  PloverPackageSetClass)
   23.19 -#define PLOVER_IS_PACKAGE_SET(obj)\
   23.20 -				G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   23.21 -				  PLOVER_TYPE_PACKAGE_SET)
   23.22 -#define PLOVER_IS_PACKAGE_SET_CLASS(klass)\
   23.23 -				G_TYPE_CHECK_CLASS_TYPE(obj,\
   23.24 -				  PLOVER_TYPE_PACKAGE_SET)
   23.25 -#define PLOVER_PACKAGE_SET_GET_CLASS(obj)\
   23.26 -				G_TYPE_INSTANCE_GET_CLASS(obj,\
   23.27 -				  PLOVER_TYPE_PACKAGE_SET,\
   23.28 -				  PloverPackageSetClass)
   23.29 -
   23.30 -typedef struct _PloverPackageSet {
   23.31 -    GObject parent_instance;
   23.32 -} PloverPackageSet;
   23.33 -
   23.34 -typedef struct _PloverPackageSetClass {
   23.35 -    GObjectClass parent_class;
   23.36 -} PloverPackageSetClass;
   23.37 -
   23.38 -GType plover_package_set_get_type(void) G_GNUC_CONST;
   23.39 -PloverPackageSet *plover_package_set_new(void);
   23.40 -PloverPackageSet *plover_package_set_new_from_installed(const char *root,
   23.41 -  GError **err);
   23.42 -PloverPackageSet *plover_package_set_new_from_repository(const char *base,
   23.43 -  struct razor_relocations *relocations,GError **err);
   23.44 -GSList *plover_package_set_get_packages(PloverPackageSet *set);
   23.45 -gboolean plover_package_set_get_no_details(PloverPackageSet *set);
   23.46 -
   23.47 -G_END_DECLS
   23.48 -
   23.49 -#endif /* __PLOVER_PACKAGE_SET_H__ */
    24.1 --- a/plover-gtk/packagestore.c	Fri Mar 23 20:29:50 2012 +0000
    24.2 +++ b/plover-gtk/packagestore.c	Sat Nov 15 19:04:45 2014 +0000
    24.3 @@ -24,7 +24,7 @@
    24.4  #include <gtk/gtk.h>
    24.5  #include <razor.h>
    24.6  #include "plover/plover.h"
    24.7 -#include "plover-gtk/package.h"
    24.8 +#include "plover/package.h"
    24.9  #include "plover-gtk/packagestore.h"
   24.10  
   24.11  #define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \
   24.12 @@ -139,6 +139,8 @@
   24.13      char *s;
   24.14      PloverPackageStore *store=(PloverPackageStore *)tree_model;
   24.15      PloverPackage *package;
   24.16 +    GInputStream *stream;
   24.17 +    GdkPixbuf *icon;
   24.18      g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_STORE_NO_COLUMNS);
   24.19      g_return_if_fail(VALID_ITER(iter,store));
   24.20      package=PLOVER_PACKAGE(g_sequence_get(iter->user_data));
   24.21 @@ -151,7 +153,15 @@
   24.22  	case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN:
   24.23  	    break;
   24.24  	case PLOVER_PACKAGE_STORE_ICON_COLUMN:
   24.25 -	    g_value_set_object(value,plover_package_get_icon(package));
   24.26 +	    stream=plover_package_read_icon(package,NULL);
   24.27 +	    if (stream)
   24.28 +	    {
   24.29 +		icon=gdk_pixbuf_new_from_stream(stream,NULL,NULL);
   24.30 +		g_object_unref(stream);
   24.31 +	    }
   24.32 +	    else
   24.33 +		icon=NULL;
   24.34 +	    g_value_set_object(value,icon);
   24.35  	    break;
   24.36  	case PLOVER_PACKAGE_STORE_NAME_COLUMN:
   24.37  	    g_value_set_string(value,plover_package_get_name(package));
    25.1 --- a/plover-gtk/packagestore.h	Fri Mar 23 20:29:50 2012 +0000
    25.2 +++ b/plover-gtk/packagestore.h	Sat Nov 15 19:04:45 2014 +0000
    25.3 @@ -2,7 +2,7 @@
    25.4  #define __PLOVER_PACKAGE_STORE_H__
    25.5  
    25.6  #include <glib-object.h>
    25.7 -#include <plover-gtk/packageset.h>
    25.8 +#include <plover/packageset.h>
    25.9  
   25.10  G_BEGIN_DECLS
   25.11  
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/plover-gtk/software-installation.ui	Sat Nov 15 19:04:45 2014 +0000
    26.3 @@ -0,0 +1,175 @@
    26.4 +<?xml version="1.0"?>
    26.5 +<interface>
    26.6 +  <requires lib="gtk+" version="2.16"/>
    26.7 +  <!-- interface-naming-policy project-wide -->
    26.8 +  <object class="GtkAssistant" id="SoftwareInstallation">
    26.9 +    <property name="border_width">12</property>
   26.10 +    <property name="title" translatable="yes">Software Installation</property>
   26.11 +    <signal name="delete_event" handler="gtk_main_quit"/>
   26.12 +    <child>
   26.13 +      <placeholder/>
   26.14 +    </child>
   26.15 +    <child>
   26.16 +      <placeholder/>
   26.17 +    </child>
   26.18 +    <child>
   26.19 +      <object class="GtkLabel" id="SIIntroduction">
   26.20 +        <property name="visible">True</property>
   26.21 +        <property name="xalign">0</property>
   26.22 +        <property name="yalign">0</property>
   26.23 +        <property name="xpad">16</property>
   26.24 +        <property name="ypad">16</property>
   26.25 +        <property name="label" translatable="yes">&lt;b&gt;Welcome to the Installation Assistant&lt;/b&gt;
   26.26 +
   26.27 +The Installation Assistant will install the software.
   26.28 +To continue, click Forward.</property>
   26.29 +        <property name="use_markup">True</property>
   26.30 +      </object>
   26.31 +      <packing>
   26.32 +        <property name="page_type">intro</property>
   26.33 +        <property name="title" translatable="yes">Software Installation</property>
   26.34 +      </packing>
   26.35 +    </child>
   26.36 +    <child>
   26.37 +      <object class="GtkVBox" id="SIConfirm">
   26.38 +        <property name="visible">True</property>
   26.39 +        <property name="orientation">vertical</property>
   26.40 +        <child>
   26.41 +          <object class="GtkVBox" id="SIIncompatibleInstallation">
   26.42 +            <property name="orientation">vertical</property>
   26.43 +            <child>
   26.44 +              <object class="GtkLabel" id="SIIncompatibleInstallationLabel">
   26.45 +                <property name="visible">True</property>
   26.46 +                <property name="xalign">0</property>
   26.47 +                <property name="yalign">0</property>
   26.48 +                <property name="xpad">16</property>
   26.49 +                <property name="ypad">16</property>
   26.50 +                <property name="label" translatable="yes">&lt;b&gt;Incompatible Installation&lt;/b&gt;
   26.51 +
   26.52 +The existing installation is not from %s
   26.53 +In order to continue, all the existing packages must be removed.</property>
   26.54 +                <property name="use_markup">True</property>
   26.55 +              </object>
   26.56 +              <packing>
   26.57 +                <property name="expand">False</property>
   26.58 +                <property name="position">0</property>
   26.59 +              </packing>
   26.60 +            </child>
   26.61 +            <child>
   26.62 +              <object class="GtkAlignment" id="alignment4">
   26.63 +                <property name="visible">True</property>
   26.64 +                <property name="left_padding">16</property>
   26.65 +                <property name="right_padding">16</property>
   26.66 +                <child>
   26.67 +                  <object class="GtkCheckButton" id="SIRemoveExisting">
   26.68 +                    <property name="label" translatable="yes">Remove all existing packages</property>
   26.69 +                    <property name="visible">True</property>
   26.70 +                    <property name="can_focus">True</property>
   26.71 +                    <property name="receives_default">False</property>
   26.72 +                    <property name="draw_indicator">True</property>
   26.73 +                  </object>
   26.74 +                </child>
   26.75 +              </object>
   26.76 +              <packing>
   26.77 +                <property name="expand">False</property>
   26.78 +                <property name="position">1</property>
   26.79 +              </packing>
   26.80 +            </child>
   26.81 +          </object>
   26.82 +          <packing>
   26.83 +            <property name="expand">False</property>
   26.84 +            <property name="position">0</property>
   26.85 +          </packing>
   26.86 +        </child>
   26.87 +        <child>
   26.88 +          <object class="GtkLabel" id="SISummaryOfWork">
   26.89 +            <property name="width_request">450</property>
   26.90 +            <property name="visible">True</property>
   26.91 +            <property name="xalign">0</property>
   26.92 +            <property name="yalign">0</property>
   26.93 +            <property name="xpad">16</property>
   26.94 +            <property name="ypad">16</property>
   26.95 +            <property name="label" translatable="yes">&lt;b&gt;Installation Summary&lt;/b&gt;
   26.96 +
   26.97 +Packages to be installed or updated: ... plus dependencies.</property>
   26.98 +            <property name="use_markup">True</property>
   26.99 +            <property name="wrap">True</property>
  26.100 +          </object>
  26.101 +          <packing>
  26.102 +            <property name="position">1</property>
  26.103 +          </packing>
  26.104 +        </child>
  26.105 +      </object>
  26.106 +      <packing>
  26.107 +        <property name="page_type">confirm</property>
  26.108 +        <property name="title" translatable="yes">Software Installation (2 of 4)</property>
  26.109 +      </packing>
  26.110 +    </child>
  26.111 +    <child>
  26.112 +      <object class="GtkVBox" id="SIProgress">
  26.113 +        <property name="visible">True</property>
  26.114 +        <property name="orientation">vertical</property>
  26.115 +        <child>
  26.116 +          <object class="GtkLabel" id="label1">
  26.117 +            <property name="visible">True</property>
  26.118 +            <property name="xalign">0</property>
  26.119 +            <property name="yalign">0</property>
  26.120 +            <property name="xpad">16</property>
  26.121 +            <property name="ypad">16</property>
  26.122 +            <property name="label" translatable="yes">&lt;b&gt;Installing the Software&lt;/b&gt;
  26.123 +
  26.124 +Please wait while the Installation Assistant installs the software.
  26.125 +This may take several minutes.</property>
  26.126 +            <property name="use_markup">True</property>
  26.127 +          </object>
  26.128 +          <packing>
  26.129 +            <property name="expand">False</property>
  26.130 +            <property name="position">0</property>
  26.131 +          </packing>
  26.132 +        </child>
  26.133 +        <child>
  26.134 +          <object class="GtkAlignment" id="alignment2">
  26.135 +            <property name="visible">True</property>
  26.136 +            <property name="bottom_padding">16</property>
  26.137 +            <property name="left_padding">16</property>
  26.138 +            <property name="right_padding">16</property>
  26.139 +            <child>
  26.140 +              <object class="GtkProgressBar" id="SIProgressBar">
  26.141 +                <property name="visible">True</property>
  26.142 +                <property name="activity_mode">True</property>
  26.143 +                <property name="show_text">True</property>
  26.144 +                <property name="text" translatable="yes">Unpacking files</property>
  26.145 +              </object>
  26.146 +            </child>
  26.147 +          </object>
  26.148 +          <packing>
  26.149 +            <property name="expand">False</property>
  26.150 +            <property name="position">1</property>
  26.151 +          </packing>
  26.152 +        </child>
  26.153 +      </object>
  26.154 +      <packing>
  26.155 +        <property name="page_type">progress</property>
  26.156 +        <property name="title" translatable="yes">Software Installation (3 of 4)</property>
  26.157 +      </packing>
  26.158 +    </child>
  26.159 +    <child>
  26.160 +      <object class="GtkLabel" id="SISummary">
  26.161 +        <property name="visible">True</property>
  26.162 +        <property name="xalign">0</property>
  26.163 +        <property name="yalign">0</property>
  26.164 +        <property name="xpad">16</property>
  26.165 +        <property name="ypad">16</property>
  26.166 +        <property name="label" translatable="yes">&lt;b&gt;Installation Assistant Completed&lt;/b&gt;
  26.167 +
  26.168 +The Installation Assistant has successfully completed.
  26.169 +Click Close to exit the Assistant.</property>
  26.170 +        <property name="use_markup">True</property>
  26.171 +      </object>
  26.172 +      <packing>
  26.173 +        <property name="page_type">summary</property>
  26.174 +        <property name="title" translatable="yes">Software Installation (4 of 4)</property>
  26.175 +      </packing>
  26.176 +    </child>
  26.177 +  </object>
  26.178 +</interface>
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/plover-gtk/stockicons.c	Sat Nov 15 19:04:45 2014 +0000
    27.3 @@ -0,0 +1,141 @@
    27.4 +/*
    27.5 + * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
    27.6 + *
    27.7 + * This program is free software; you can redistribute it and/or modify
    27.8 + * it under the terms of the GNU General Public License as published by
    27.9 + * the Free Software Foundation; either version 2 of the License, or
   27.10 + * (at your option) any later version.
   27.11 + *
   27.12 + * This program is distributed in the hope that it will be useful,
   27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.15 + * GNU General Public License for more details.
   27.16 + *
   27.17 + * You should have received a copy of the GNU General Public License along
   27.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   27.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   27.20 + */
   27.21 +
   27.22 +#include "config.h"
   27.23 +#include <stdlib.h>
   27.24 +#ifdef WIN32
   27.25 +#include <windows.h>
   27.26 +#endif	/* WIN32 */
   27.27 +#include <glib.h>
   27.28 +#include <gtk/gtk.h>
   27.29 +#include <plover-gtk/stockicons.h>
   27.30 +
   27.31 +/* Checks whether a loader for SVG files has been registered
   27.32 + * with GdkPixbuf.
   27.33 + */
   27.34 +static gboolean plover_pixbuf_supports_svg(void)
   27.35 +{
   27.36 +    GSList *formats;
   27.37 +    GSList *tmp_list;
   27.38 +    static gint found_svg=-1;
   27.39 +    gchar **mime_types,**mime_type;
   27.40 +    if (found_svg!=-1)
   27.41 +	return found_svg;
   27.42 +    formats=gdk_pixbuf_get_formats();
   27.43 +    found_svg=FALSE;
   27.44 +    for (tmp_list=formats;tmp_list && !found_svg;tmp_list=tmp_list->next)
   27.45 +    {
   27.46 +	mime_types=gdk_pixbuf_format_get_mime_types(tmp_list->data);
   27.47 +	for (mime_type=mime_types;*mime_type && !found_svg;mime_type++)
   27.48 +	    if (!strcmp(*mime_type,"image/svg"))
   27.49 +		found_svg=TRUE;
   27.50 +	g_strfreev(mime_types);
   27.51 +    }
   27.52 +    g_slist_free(formats);
   27.53 +    return found_svg;
   27.54 +}
   27.55 +
   27.56 +static void plover_install_icon_at_size(const char *icon_name,
   27.57 +  GtkIconSet *icon_set,GtkIconSize size,const char *filename)
   27.58 +{
   27.59 +    int w,h;
   27.60 +    GdkPixbuf *pixbuf;
   27.61 +    GtkIconSource *source;
   27.62 +    if (gtk_icon_size_lookup(size,&w,&h))
   27.63 +    {
   27.64 +	pixbuf=gdk_pixbuf_new_from_file_at_size(filename,w,h,NULL);
   27.65 +	if (pixbuf)
   27.66 +	{
   27.67 +	    source=gtk_icon_source_new();
   27.68 +	    gtk_icon_source_set_size_wildcarded(source,FALSE);
   27.69 +	    gtk_icon_source_set_size(source,size);
   27.70 +	    gtk_icon_source_set_pixbuf(source,pixbuf);
   27.71 +	    gtk_icon_set_add_source(icon_set,source);
   27.72 +	    gtk_icon_source_free(source);
   27.73 +	    g_object_unref(pixbuf);
   27.74 +	}
   27.75 +    }
   27.76 +}
   27.77 +
   27.78 +/**
   27.79 + * plover_icons_add_to_stock:
   27.80 + * @type: The icon type, typically "apps" or "mimetype"
   27.81 + * @name: The icon name (the basename of files containing the icons)
   27.82 + *
   27.83 + * Find icons in <datadir>/icons/hicolor and add them to the stock images
   27.84 + * so that, for example, gtk_image_new_from_stock() will be able find them.
   27.85 + *
   27.86 + * If there is an SVG loader registered with GdkPixbuf, then:
   27.87 + * <datadir>/icons/hicolor/scalable/@type/@name.svg will be used. Otherwise,
   27.88 + * <datadir>/icons/hicolor/24x24/@type/@name.png and
   27.89 + * <datadir>/icons/hicolor/48x48/@type/@name.png will be used.
   27.90 + */
   27.91 +void plover_icons_add_to_stock(const char *type,const char *name)
   27.92 +{
   27.93 +    gchar *prefix,*s,*filename;
   27.94 +    GtkIconSource *source;
   27.95 +    GtkIconSet *icon_set;
   27.96 +    GtkIconFactory *factory;
   27.97 +    factory=gtk_icon_factory_new();
   27.98 +    icon_set=gtk_icon_set_new();
   27.99 +#ifdef WIN32
  27.100 +    prefix=g_win32_get_package_installation_directory_of_module(NULL);
  27.101 +#else
  27.102 +    prefix=NULL;
  27.103 +#endif
  27.104 +    if (plover_pixbuf_supports_svg())
  27.105 +    {
  27.106 +	source=gtk_icon_source_new();
  27.107 +	s=g_strconcat(name,".svg");
  27.108 +	filename=g_build_filename(prefix?prefix:"/usr",
  27.109 +	  "share/icons/hicolor/scalable",type,s,NULL);
  27.110 +	g_free(s);
  27.111 +	gtk_icon_source_set_filename(source,filename);
  27.112 +	g_free(filename);
  27.113 +	gtk_icon_set_add_source(icon_set,source);
  27.114 +	gtk_icon_source_free(source);
  27.115 +    }
  27.116 +    else
  27.117 +    {
  27.118 +	s=g_strconcat(name,".png");
  27.119 +	filename=g_build_filename(prefix?prefix:"/usr",
  27.120 +	  "share/icons/hicolor/24x24",type,s,NULL);
  27.121 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_MENU,
  27.122 +	  filename);
  27.123 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_BUTTON,
  27.124 +	  filename);
  27.125 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_SMALL_TOOLBAR,
  27.126 +	  filename);
  27.127 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_LARGE_TOOLBAR,
  27.128 +	  filename);
  27.129 +	g_free(filename);
  27.130 +	filename=g_build_filename(prefix?prefix:"/usr",
  27.131 +	  "share/icons/hicolor/48x48",type,s,NULL);
  27.132 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_DND,
  27.133 +	  filename);
  27.134 +	plover_install_icon_at_size(name,icon_set,GTK_ICON_SIZE_DIALOG,
  27.135 +	  filename);
  27.136 +	g_free(filename);
  27.137 +	g_free(s);
  27.138 +    }
  27.139 +    gtk_icon_factory_add(factory,name,icon_set);
  27.140 +    gtk_icon_set_unref(icon_set);
  27.141 +    //icon_set=gtk_icon_factory_lookup(factory,name);
  27.142 +    gtk_icon_factory_add_default(factory);
  27.143 +    g_object_unref(factory);
  27.144 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/plover-gtk/stockicons.h	Sat Nov 15 19:04:45 2014 +0000
    28.3 @@ -0,0 +1,6 @@
    28.4 +#ifndef __PLOVER_STOCK_ICONS_H__
    28.5 +#define __PLOVER_STOCK_ICONS_H__
    28.6 +
    28.7 +void plover_icons_add_to_stock(const char *type,const char *name);
    28.8 +
    28.9 +#endif /* __PLOVER_STOCK_ICONS_H__ */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/plover-gtk/transactionhelper.c	Sat Nov 15 19:04:45 2014 +0000
    29.3 @@ -0,0 +1,1037 @@
    29.4 +/*
    29.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    29.6 + *
    29.7 + * This program is free software; you can redistribute it and/or modify
    29.8 + * it under the terms of the GNU General Public License as published by
    29.9 + * the Free Software Foundation; either version 2 of the License, or
   29.10 + * (at your option) any later version.
   29.11 + *
   29.12 + * This program is distributed in the hope that it will be useful,
   29.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.15 + * GNU General Public License for more details.
   29.16 + *
   29.17 + * You should have received a copy of the GNU General Public License along
   29.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   29.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   29.20 + */
   29.21 +
   29.22 +#include "config.h"
   29.23 +#include <stdlib.h>
   29.24 +#include <errno.h>
   29.25 +#include <gtk/gtk.h>
   29.26 +#include <plover/plover.h>
   29.27 +#include <plover/transaction.h>
   29.28 +#include <plover-gtk/transactionhelper.h>
   29.29 +
   29.30 +/*
   29.31 + * A PloverTransactionHelper uses a GtkAssistant to help a user run a
   29.32 + * transaction.
   29.33 + */
   29.34 +
   29.35 +G_DEFINE_TYPE(PloverTransactionHelper,plover_transaction_helper,G_TYPE_OBJECT)
   29.36 +
   29.37 +enum {
   29.38 +    CLOSE=0,
   29.39 +    N_SIGNALS
   29.40 +};
   29.41 +
   29.42 +static guint signals[N_SIGNALS];
   29.43 +
   29.44 +static void plover_transaction_helper_finalize(PloverTransactionHelper *helper)
   29.45 +{
   29.46 +    g_free(helper->error_primary_text);
   29.47 +    g_free(helper->base);
   29.48 +    g_free(helper->unsatisfied);
   29.49 +    if (helper->comps)
   29.50 +	plover_comps_free(helper->comps);
   29.51 +    plover_vector_free(helper->report_adding);
   29.52 +    plover_vector_free(helper->report_removing);
   29.53 +}
   29.54 +
   29.55 +static void plover_transaction_helper_dispose(PloverTransactionHelper *helper)
   29.56 +{
   29.57 +    g_clear_error(&helper->error);
   29.58 +    if (helper->error_dialog)
   29.59 +    {
   29.60 +	g_signal_handlers_disconnect_by_data(helper->error_dialog,helper);
   29.61 +	gtk_widget_destroy(helper->error_dialog);
   29.62 +	helper->error_dialog=NULL;
   29.63 +    }
   29.64 +    if (helper->assistant)
   29.65 +    {
   29.66 +	g_signal_handlers_disconnect_by_data(helper->assistant,helper);
   29.67 +	g_clear_object(&helper->assistant);
   29.68 +    }
   29.69 +    g_clear_object(&helper->ui);
   29.70 +    g_slist_foreach(helper->transactions,(GFunc)g_object_unref,NULL);
   29.71 +    g_slist_free(helper->transactions);
   29.72 +    helper->transactions=NULL;
   29.73 +    g_clear_object(&helper->installed);
   29.74 +    g_clear_object(&helper->upstream);
   29.75 +    g_clear_object(&helper->relocated_upstream);
   29.76 +}
   29.77 +
   29.78 +static void
   29.79 +  plover_transaction_helper_class_init(PloverTransactionHelperClass *klass)
   29.80 +{
   29.81 +    GObjectClass *gobject_class=G_OBJECT_CLASS(klass);
   29.82 +    gobject_class->finalize=
   29.83 +      (void (*)(GObject *))plover_transaction_helper_finalize;
   29.84 +    gobject_class->dispose=
   29.85 +      (void (*)(GObject *))plover_transaction_helper_dispose;
   29.86 +    signals[CLOSE]=g_signal_newv("close",
   29.87 +      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
   29.88 +      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
   29.89 +}
   29.90 +
   29.91 +static void plover_transaction_helper_init(PloverTransactionHelper *helper)
   29.92 +{
   29.93 +    helper->report_adding=plover_vector_new();
   29.94 +    helper->report_removing=plover_vector_new();
   29.95 +}
   29.96 +
   29.97 +static void plover_transaction_helper_assistant_cancel(GtkAssistant *assistant,
   29.98 +  PloverTransactionHelper *helper)
   29.99 +{
  29.100 +    gtk_widget_hide(GTK_WIDGET(helper->assistant));
  29.101 +    gtk_assistant_set_current_page(helper->assistant,0);
  29.102 +    g_signal_emit(helper,signals[CLOSE],0);
  29.103 +}
  29.104 +
  29.105 +static void plover_transaction_helper_assistant_close(GtkAssistant *assistant,
  29.106 +  PloverTransactionHelper *helper)
  29.107 +{
  29.108 +    gtk_widget_hide(GTK_WIDGET(helper->assistant));
  29.109 +    gtk_assistant_set_current_page(helper->assistant,0);
  29.110 +    g_signal_emit(helper,signals[CLOSE],0);
  29.111 +}
  29.112 +
  29.113 +static void
  29.114 +  plover_transaction_helper_prepare_confirm(PloverTransactionHelper *helper)
  29.115 +{
  29.116 +    gchar *package_list,*add,*remove,*s;
  29.117 +    GtkLabel *label;
  29.118 +    struct plover_vector *report;
  29.119 +    if (helper->report_adding->len)
  29.120 +    {
  29.121 +	plover_vector_sort(helper->report_adding);
  29.122 +	if (helper->report_adding_dependencies)
  29.123 +	{
  29.124 +	    report=plover_vector_dup(helper->report_adding);
  29.125 +	    if (helper->report_adding->len==1)
  29.126 +		plover_vector_append(report,"its dependencies");
  29.127 +	    else
  29.128 +		plover_vector_append(report,"their dependencies");
  29.129 +	    package_list=plover_vector_format_for_display(report);
  29.130 +	    plover_vector_free(report);
  29.131 +	}
  29.132 +	else
  29.133 +	    package_list=
  29.134 +	      plover_vector_format_for_display(helper->report_adding);
  29.135 +	add=g_strconcat("Packages to be installed or updated: ",package_list,
  29.136 +	  ".",NULL);
  29.137 +	g_free(package_list);
  29.138 +    }
  29.139 +    else
  29.140 +	add=NULL;
  29.141 +    if (helper->report_removing->len)
  29.142 +    {
  29.143 +	plover_vector_sort(helper->report_removing);
  29.144 +	if (helper->report_removing_dependants)
  29.145 +	{
  29.146 +	    report=plover_vector_dup(helper->report_removing);
  29.147 +	    if (helper->report_adding->len==1)
  29.148 +		plover_vector_append(report,"its dependants");
  29.149 +	    else
  29.150 +		plover_vector_append(report,"their dependants");
  29.151 +	    package_list=plover_vector_format_for_display(report);
  29.152 +	    plover_vector_free(report);
  29.153 +	}
  29.154 +	else
  29.155 +	    package_list=
  29.156 +	      plover_vector_format_for_display(helper->report_removing);
  29.157 +	remove=g_strconcat("Packages to be removed: ",package_list,".",NULL);
  29.158 +	g_free(package_list);
  29.159 +    }
  29.160 +    else
  29.161 +	remove=NULL;
  29.162 +    label=GTK_LABEL(gtk_builder_get_object(helper->ui,"SISummaryOfWork"));
  29.163 +    if (add && remove)
  29.164 +	s=g_strconcat("<b>Installation Summary</b>\n\n",remove,"\n\n",add,NULL);
  29.165 +    else if (add || remove)
  29.166 +	s=g_strconcat("<b>Installation Summary</b>\n\n",add?add:remove,NULL);
  29.167 +    else
  29.168 +	s=g_strdup("<b>Installation Summary</b>\n\nNo changes scheduled");
  29.169 +    gtk_label_set_markup(label,s);
  29.170 +    g_free(s);
  29.171 +    g_free(add);
  29.172 +    g_free(remove);
  29.173 +}
  29.174 +
  29.175 +static void plover_transaction_helper_run(PloverTransactionHelper *helper);
  29.176 +
  29.177 +static void plover_transaction_helper_callback(GObject *source,
  29.178 +  GAsyncResult *result,gpointer user_data)
  29.179 +{
  29.180 +    GError *error=NULL;
  29.181 +    PloverTransactionHelper *helper=user_data;
  29.182 +    PloverTransaction *transaction=PLOVER_TRANSACTION(source);
  29.183 +    if (!plover_transaction_commit_finish(transaction,result,&error))
  29.184 +    {
  29.185 +	plover_transaction_helper_set_error(helper,error,
  29.186 +	  "Software installation failed");
  29.187 +	g_error_free(error);
  29.188 +    }
  29.189 +    else
  29.190 +	plover_transaction_helper_run(helper);
  29.191 +    g_signal_handlers_disconnect_by_data(transaction,helper);
  29.192 +    g_object_unref(transaction);
  29.193 +}
  29.194 +
  29.195 +static void plover_transaction_helper_transaction_status_changed(
  29.196 +  PloverTransaction *transaction,const char *status,
  29.197 +  PloverTransactionHelper *helper)
  29.198 +{
  29.199 +    GtkProgressBar *bar;
  29.200 +    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
  29.201 +    gtk_progress_bar_set_text(bar,status);
  29.202 +}
  29.203 +
  29.204 +static void plover_transaction_helper_run(PloverTransactionHelper *helper)
  29.205 +{
  29.206 +    PloverTransaction *transaction;
  29.207 +    GtkWidget *page;
  29.208 +    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
  29.209 +    if (helper->transactions)
  29.210 +    {
  29.211 +	if (helper->assistant)
  29.212 +	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
  29.213 +	transaction=helper->transactions->data;
  29.214 +	helper->transactions=g_slist_delete_link(helper->transactions,
  29.215 +	  helper->transactions);
  29.216 +	g_signal_connect(transaction,"status-changed",
  29.217 +	  G_CALLBACK(plover_transaction_helper_transaction_status_changed),
  29.218 +	  helper);
  29.219 +	plover_transaction_commit_async(transaction,NULL,
  29.220 +	  plover_transaction_helper_callback,helper);
  29.221 +    }
  29.222 +    else if (helper->assistant)
  29.223 +	gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
  29.224 +}
  29.225 +
  29.226 +static gboolean plover_transaction_helper_pulse(gpointer user_data)
  29.227 +{
  29.228 +    PloverTransactionHelper *helper=user_data;
  29.229 +    GtkWidget *w;
  29.230 +    GtkProgressBar *bar;
  29.231 +    if (!helper->assistant)
  29.232 +	return FALSE;
  29.233 +    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
  29.234 +    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
  29.235 +    if (gtk_assistant_get_page_complete(helper->assistant,w))
  29.236 +    {
  29.237 +	gtk_progress_bar_set_fraction(bar,1.0);
  29.238 +	helper->pulse_handler=0;
  29.239 +	return FALSE;
  29.240 +    }
  29.241 +    else
  29.242 +    {
  29.243 +	gtk_progress_bar_pulse(bar);
  29.244 +	return TRUE;
  29.245 +    }
  29.246 +}
  29.247 +
  29.248 +static void
  29.249 +  plover_transaction_helper_prepare_progress(PloverTransactionHelper *helper)
  29.250 +{
  29.251 +    GError *error=NULL;
  29.252 +    GtkToggleButton *button;
  29.253 +    PloverTransaction *transaction;
  29.254 +    button=GTK_TOGGLE_BUTTON(gtk_builder_get_object(helper->ui,
  29.255 +      "SIRemoveExisting"));
  29.256 +    if (gtk_toggle_button_get_active(button))
  29.257 +    {
  29.258 +	transaction=plover_transaction_new_remove(NULL,&error);
  29.259 +	if (!transaction)
  29.260 +	{
  29.261 +	    if (g_error_matches(error,PLOVER_POSIX_ERROR,ENOENT))
  29.262 +		g_clear_error(&error);
  29.263 +	    if (error)
  29.264 +	    {
  29.265 +		plover_transaction_helper_set_error(helper,error,
  29.266 +		  "Software installation failed");
  29.267 +		g_error_free(error);
  29.268 +		return;
  29.269 +	    }
  29.270 +	}
  29.271 +	else
  29.272 +	    helper->transactions=
  29.273 +	      g_slist_prepend(helper->transactions,transaction);
  29.274 +    }
  29.275 +    /*
  29.276 +     * Note that PloverTransaction does support cancelling a transaction, but
  29.277 +     * there are a number of challenges with using it:
  29.278 +     *	- cancellation is only supported during the file phase if razor
  29.279 +     *	  has atomic rollback,
  29.280 +     *  - cancellation is not supported during post-transaction scripts at all
  29.281 +     *    (since by the time the first script is started the atomic has already
  29.282 +     *    been committed) and these can take quite some time,
  29.283 +     *  - where a transaction has an embedded COMMIT, any rollback won't
  29.284 +     *    go back beyond this point.
  29.285 +     * To support user-cancel, then, we would need some mechanism to:
  29.286 +     *  - Comunicate that the operation is being cancelled and this may take
  29.287 +     *    some time,
  29.288 +     *  - Not allow cancellation at all after the last post-transaction script
  29.289 +     *    phase is started,
  29.290 +     *  - Report the partially completed transaction where cancellation
  29.291 +     *    occurred after a COMMIT point.
  29.292 +     * At present, this doesn't appear worth the effort.
  29.293 +     */
  29.294 +    if (helper->assistant)
  29.295 +	gtk_assistant_commit(helper->assistant);
  29.296 +    plover_transaction_helper_run(helper);
  29.297 +    helper->pulse_handler=g_timeout_add(100,plover_transaction_helper_pulse,
  29.298 +      helper);
  29.299 +}
  29.300 +
  29.301 +static void plover_transaction_helper_assistant_prepare(GtkAssistant *assistant,
  29.302 +  GtkWidget *page,PloverTransactionHelper *helper)
  29.303 +{
  29.304 +    if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm")))
  29.305 +	plover_transaction_helper_prepare_confirm(helper);
  29.306 +    else if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress")))
  29.307 +	plover_transaction_helper_prepare_progress(helper);
  29.308 +}
  29.309 +
  29.310 +static void
  29.311 +  plover_transaction_helper_remove_existing_toggled(GtkToggleButton *button,
  29.312 +  PloverTransactionHelper *helper)
  29.313 +{
  29.314 +    GtkWidget *w;
  29.315 +    if (helper->assistant)
  29.316 +    {
  29.317 +	w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
  29.318 +	gtk_assistant_set_page_complete(helper->assistant,w,
  29.319 +	  gtk_toggle_button_get_active(button));
  29.320 +    }
  29.321 +}
  29.322 +
  29.323 +PloverTransactionHelper *plover_transaction_helper_new(GtkBuilder *ui)
  29.324 +{
  29.325 +    gsize len;
  29.326 +    gchar *s,*directory,*contents;
  29.327 +    GError *error=NULL;
  29.328 +    GtkWidget *w;
  29.329 +    PloverTransactionHelper *helper;
  29.330 +    g_return_val_if_fail(ui == NULL || GTK_IS_BUILDER(ui),NULL);
  29.331 +    helper=PLOVER_TRANSACTION_HELPER(
  29.332 +      g_object_new(PLOVER_TYPE_TRANSACTION_HELPER,NULL));
  29.333 +    if (ui)
  29.334 +	helper->ui=g_object_ref(ui);
  29.335 +    else
  29.336 +	helper->ui=gtk_builder_new();
  29.337 +    helper->assistant=
  29.338 +      GTK_ASSISTANT(gtk_builder_get_object(helper->ui,"SoftwareInstallation"));
  29.339 +    if (!helper->assistant)
  29.340 +    {
  29.341 +	directory=g_strdup(g_getenv("PLOVER_DATADIR"));
  29.342 +	if (!directory)
  29.343 +	{
  29.344 +#ifdef WIN32
  29.345 +	    s=g_win32_get_package_installation_directory_of_module(NULL);
  29.346 +	    directory=g_build_filename(s,"share","plover",NULL);
  29.347 +	    g_free(s);
  29.348 +#else
  29.349 +	    directory=g_strdup(PLOVER_DATADIR);
  29.350 +#endif
  29.351 +	}
  29.352 +	s=g_build_filename(directory,"software-installation.ui",NULL);
  29.353 +	g_free(directory);
  29.354 +	(void)g_file_get_contents(s,&contents,&len,&error);
  29.355 +	g_free(s);
  29.356 +	if (!error)
  29.357 +	{
  29.358 +	    (void)gtk_builder_add_from_string(helper->ui,contents,len,&error);
  29.359 +	    g_free(contents);
  29.360 +	}
  29.361 +	if (error)
  29.362 +	{
  29.363 +	    g_critical("software-installation.ui: %s",error->message);
  29.364 +	    g_clear_error(&error);
  29.365 +	    g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  29.366 +	      "Internal error (no user interface)");
  29.367 +	    plover_transaction_helper_set_error(helper,error,
  29.368 +	      "Can't start installer");
  29.369 +	    return helper;
  29.370 +	}
  29.371 +	helper->assistant=GTK_ASSISTANT(gtk_builder_get_object(helper->ui,
  29.372 +	  "SoftwareInstallation"));
  29.373 +    }
  29.374 +    if (!helper->assistant)
  29.375 +    {
  29.376 +	g_critical("\"SoftwareInstallation\" object not found");
  29.377 +	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  29.378 +	  "Internal error (missing wizard)");
  29.379 +	plover_transaction_helper_set_error(helper,error,
  29.380 +	  "Can't start installer");
  29.381 +	g_error_free(error);
  29.382 +	return helper;
  29.383 +    }
  29.384 +    else
  29.385 +	g_object_ref(helper->assistant);
  29.386 +    if (!GTK_IS_ASSISTANT(helper->assistant))
  29.387 +    {
  29.388 +	g_critical("\"SoftwareInstallation\" is not a GtkAssistant");
  29.389 +	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  29.390 +	  "Internal error (unexpected wizard type)");
  29.391 +	plover_transaction_helper_set_error(helper,error,
  29.392 +	  "Can't start installer");
  29.393 +	g_error_free(error);
  29.394 +	return helper;
  29.395 +    }
  29.396 +    g_signal_connect(helper->assistant,"cancel",
  29.397 +      G_CALLBACK(plover_transaction_helper_assistant_cancel),helper);
  29.398 +    g_signal_connect(helper->assistant,"close",
  29.399 +      G_CALLBACK(plover_transaction_helper_assistant_close),helper);
  29.400 +    g_signal_connect(helper->assistant,"prepare",
  29.401 +      G_CALLBACK(plover_transaction_helper_assistant_prepare),helper);
  29.402 +    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
  29.403 +    if (w)
  29.404 +	g_signal_connect(w,"toggled",
  29.405 +	  G_CALLBACK(plover_transaction_helper_remove_existing_toggled),helper);
  29.406 +    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIIntroduction"));
  29.407 +    if (w)
  29.408 +	gtk_assistant_set_page_complete(helper->assistant,w,TRUE);
  29.409 +    return helper;
  29.410 +}
  29.411 +
  29.412 +PloverPackageSet *
  29.413 +  plover_transaction_helper_get_installed(PloverTransactionHelper *helper)
  29.414 +{
  29.415 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.416 +    return helper->installed;
  29.417 +}
  29.418 +
  29.419 +void plover_transaction_helper_set_installed(PloverTransactionHelper *helper,
  29.420 +  PloverPackageSet *installed)
  29.421 +{
  29.422 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.423 +    g_return_if_fail(PLOVER_IS_PACKAGE_SET(installed));
  29.424 +    g_return_if_fail(helper->installed == NULL);
  29.425 +    helper->installed=g_object_ref(installed);
  29.426 +}
  29.427 +
  29.428 +PloverRepository *
  29.429 +  plover_transaction_helper_get_upstream(PloverTransactionHelper *helper,
  29.430 +  GError **error)
  29.431 +{
  29.432 +    const char *base;
  29.433 +#if 0
  29.434 +    const char *prefix;
  29.435 +    struct razor_relocations *relocations=NULL;
  29.436 +#endif
  29.437 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.438 +    if (!helper->upstream)
  29.439 +    {
  29.440 +#if 0
  29.441 +	prefix=plover_transaction_helper_get_prefix(helper,error);
  29.442 +	if (!prefix)
  29.443 +	    return NULL;
  29.444 +#endif
  29.445 +	base=plover_transaction_helper_get_base(helper);
  29.446 +#if 0
  29.447 +	if (prefix)
  29.448 +	{
  29.449 +	    relocations=razor_relocations_create();
  29.450 +	    razor_relocations_add(relocations,"/usr",prefix);
  29.451 +	}
  29.452 +#endif
  29.453 +	helper->upstream=plover_repository_new_from_yum(base,error);
  29.454 +#if 0
  29.455 +	if (relocations)
  29.456 +	    razor_relocations_destroy(relocations);
  29.457 +#endif
  29.458 +    }
  29.459 +    return helper->upstream;
  29.460 +}
  29.461 +
  29.462 +static PloverPackageSet *plover_transaction_helper_get_relocated_upstream(
  29.463 +  PloverTransactionHelper *helper,GError **error)
  29.464 +{
  29.465 +    const char *prefix;
  29.466 +    struct razor_relocations *relocations=NULL;
  29.467 +    GError *tmp_error=NULL;
  29.468 +    PloverRepository *upstream;
  29.469 +    PloverPackageSet *set;
  29.470 +    if (!helper->relocated_upstream)
  29.471 +    {
  29.472 +	upstream=plover_transaction_helper_get_upstream(helper,error);
  29.473 +	if (!upstream)
  29.474 +	    return NULL;
  29.475 +	prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
  29.476 +	if (tmp_error)
  29.477 +	{
  29.478 +	    g_propagate_error(error,tmp_error);
  29.479 +	    return NULL;
  29.480 +	}
  29.481 +	set=plover_repository_get_package_set(upstream);
  29.482 +	if (prefix)
  29.483 +	{
  29.484 +	    relocations=razor_relocations_create();
  29.485 +	    razor_relocations_add(relocations,"/usr",prefix);
  29.486 +	    helper->relocated_upstream=
  29.487 +	      plover_package_set_new_from_repository(upstream,relocations,
  29.488 +	      error);
  29.489 +	    if (relocations)
  29.490 +		razor_relocations_destroy(relocations);
  29.491 +	}
  29.492 +	else
  29.493 +	    helper->relocated_upstream=g_object_ref(set);
  29.494 +    }
  29.495 +    return helper->relocated_upstream;
  29.496 +}
  29.497 +
  29.498 +void plover_transaction_helper_set_upstream(PloverTransactionHelper *helper,
  29.499 +  PloverRepository *upstream)
  29.500 +{
  29.501 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.502 +    g_return_if_fail(PLOVER_IS_REPOSITORY(upstream));
  29.503 +    g_return_if_fail(helper->upstream == NULL);
  29.504 +    helper->upstream=g_object_ref(upstream);
  29.505 +}
  29.506 +
  29.507 +const char *plover_transaction_helper_get_base(PloverTransactionHelper *helper)
  29.508 +{
  29.509 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.510 +    return helper->base;
  29.511 +}
  29.512 +
  29.513 +void plover_transaction_helper_set_base(PloverTransactionHelper *helper,
  29.514 +  const char *base)
  29.515 +{
  29.516 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.517 +    g_return_if_fail(helper->transactions == NULL);
  29.518 +    g_free(helper->base);
  29.519 +    helper->base=g_strdup(base);
  29.520 +}
  29.521 +
  29.522 +struct comps *
  29.523 +  plover_transaction_helper_get_comps(PloverTransactionHelper *helper,
  29.524 +  GError **error)
  29.525 +{
  29.526 +    gchar *s;
  29.527 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.528 +    g_return_val_if_fail(helper->base != NULL,NULL);
  29.529 +    if (!helper->comps)
  29.530 +    {
  29.531 +	s=g_strconcat(helper->base,"/repodata/comps.xml",NULL);
  29.532 +	helper->comps=plover_comps_new_from_file(s);
  29.533 +	if (!helper->comps)
  29.534 +	    g_set_error(error,PLOVER_GENERAL_ERROR,
  29.535 +	      PLOVER_GENERAL_ERROR_FAILED,"%s: %s",s,g_strerror(errno));
  29.536 +	g_free(s);
  29.537 +    }
  29.538 +    return helper->comps;
  29.539 +}
  29.540 +
  29.541 +const char *
  29.542 +  plover_transaction_helper_get_prefix(PloverTransactionHelper *helper,
  29.543 +  GError **error)
  29.544 +{
  29.545 +    const char *prefix;
  29.546 +    struct comps *comps;
  29.547 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.548 +    g_return_val_if_fail(helper->base != NULL || helper->installed != NULL,NULL);
  29.549 +    if (helper->base)
  29.550 +    {
  29.551 +	comps=plover_transaction_helper_get_comps(helper,error);
  29.552 +	if (!comps)
  29.553 +	    return NULL;
  29.554 +	return plover_default_prefix_for_vendor(comps->vendor);
  29.555 +    }
  29.556 +    prefix=plover_package_set_guess_prefix(helper->installed,error);
  29.557 +    return prefix;
  29.558 +}
  29.559 +
  29.560 +static int plover_transaction_helper_package_count(void)
  29.561 +{
  29.562 +    int count=0;
  29.563 +    char *install_root;
  29.564 +    struct razor_set *set;
  29.565 +    struct razor_package *package;
  29.566 +    struct razor_package_iterator *pi;
  29.567 +    install_root=getenv("RAZOR_ROOT");
  29.568 +    if (!install_root)
  29.569 +	install_root="";
  29.570 +    set=razor_root_open_read_only(install_root,NULL);
  29.571 +    if (set)
  29.572 +    {
  29.573 +	pi=razor_package_iterator_create(set);
  29.574 +	while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
  29.575 +	    count++;
  29.576 +	razor_package_iterator_destroy(pi);
  29.577 +	razor_set_unref(set);
  29.578 +    }
  29.579 +    return count;
  29.580 +}
  29.581 +
  29.582 +static gboolean
  29.583 +  plover_transaction_helper_check_vendor(PloverTransactionHelper *helper,
  29.584 +  GError **error)
  29.585 +{
  29.586 +    int i;
  29.587 +    gchar *prefix=NULL,*s;
  29.588 +    struct comps *comps=NULL;
  29.589 +    GtkWidget *container,*page;
  29.590 +    GtkButton *button;
  29.591 +    GtkLabel *label;
  29.592 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.593 +    if (helper->check_vendor)
  29.594 +    {
  29.595 +	comps=plover_transaction_helper_get_comps(helper,error);
  29.596 +	if (!comps)
  29.597 +	    return FALSE;
  29.598 +	prefix=plover_default_prefix_for_vendor(comps->vendor);
  29.599 +    }
  29.600 +    button=GTK_BUTTON(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
  29.601 +    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),FALSE);
  29.602 +    container=GTK_WIDGET(gtk_builder_get_object(helper->ui,
  29.603 +      "SIIncompatibleInstallation"));
  29.604 +    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
  29.605 +    if (helper->check_vendor && prefix &&
  29.606 +      !plover_installed_files_match_prefix(prefix))
  29.607 +    {
  29.608 +	label=GTK_LABEL(gtk_builder_get_object(helper->ui,
  29.609 +	  "SIIncompatibleInstallationLabel"));
  29.610 +	s=g_strdup_printf("<b>Incompatible Installation</b>\n\n"
  29.611 +	  "The existing installation is not from %s.\n"
  29.612 +	  "In order to continue, all the existing packages must be removed.",
  29.613 +	  comps->vendor);
  29.614 +	gtk_label_set_markup(label,s);
  29.615 +	g_free(s);
  29.616 +	i=plover_transaction_helper_package_count();
  29.617 +	s=g_strdup_printf("Remove %d existing package%s",i,i==1?"":"s");
  29.618 +	gtk_button_set_label(button,s);
  29.619 +	g_free(s);
  29.620 +	gtk_widget_show(container);
  29.621 +	if (helper->assistant)
  29.622 +	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
  29.623 +    }
  29.624 +    else
  29.625 +    {
  29.626 +	gtk_widget_hide(container);
  29.627 +	if (helper->assistant)
  29.628 +	    gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
  29.629 +    }
  29.630 +    return TRUE;
  29.631 +}
  29.632 +
  29.633 +void plover_transaction_helper_set_check_vendor(PloverTransactionHelper *helper,
  29.634 +  gboolean check_vendor)
  29.635 +{
  29.636 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.637 +    if (helper->check_vendor!=check_vendor)
  29.638 +    {
  29.639 +	helper->check_vendor=check_vendor;
  29.640 +	if (helper->transactions)
  29.641 +	    plover_transaction_helper_check_vendor(helper,NULL);
  29.642 +    }
  29.643 +}
  29.644 +
  29.645 +/*
  29.646 + * If plover_transaction_helper_add_transaction() failes with an error
  29.647 + * of PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET
  29.648 + * then plover_transaction_helper_get_unsatisfied() can be used to
  29.649 + * retrieve a textual description of the problem.
  29.650 + */
  29.651 +
  29.652 +const char *
  29.653 +  plover_transaction_helper_get_unsatisfied(PloverTransactionHelper *helper)
  29.654 +{
  29.655 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.656 +    return helper->unsatisfied;
  29.657 +}
  29.658 +
  29.659 +gboolean
  29.660 +  plover_transaction_helper_add_transaction(PloverTransactionHelper *helper,
  29.661 +  PloverTransaction *transaction,struct plover_vector *report_packages,
  29.662 +  enum razor_install_action report_action,GError **error)
  29.663 +{
  29.664 +    int i,count;
  29.665 +    gboolean other_packages;
  29.666 +    const char *s,*name;
  29.667 +    enum razor_install_action action;
  29.668 +    struct razor_install_iterator *ii;
  29.669 +    struct razor_set *next;
  29.670 +    struct razor_package *package;
  29.671 +    struct plover_vector *tasked_packages;
  29.672 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.673 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  29.674 +    g_return_val_if_fail(report_action==RAZOR_INSTALL_ACTION_ADD || report_action==RAZOR_INSTALL_ACTION_REMOVE,FALSE);
  29.675 +    g_free(helper->unsatisfied);
  29.676 +    helper->unsatisfied=NULL;
  29.677 +    if (!plover_transaction_resolve(transaction,error))
  29.678 +    {
  29.679 +	s=plover_transaction_get_unsatisfied(transaction);
  29.680 +	helper->unsatisfied=g_strdup(s);
  29.681 +	return FALSE;
  29.682 +    }
  29.683 +    ii=plover_transaction_get_install_iterator(transaction,error);
  29.684 +    if (!ii)
  29.685 +	return FALSE;
  29.686 +    next=plover_transaction_get_next_set(transaction,error);
  29.687 +    if (!next)
  29.688 +	return FALSE;
  29.689 +    tasked_packages=plover_vector_new();
  29.690 +    other_packages=FALSE;
  29.691 +    while (razor_install_iterator_next(ii,&package,&action,&count))
  29.692 +    {
  29.693 +	if (action==report_action)
  29.694 +	{
  29.695 +	    razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
  29.696 +	      RAZOR_DETAIL_LAST);
  29.697 +	    if (!report_packages ||
  29.698 +	      plover_vector_contains(report_packages,name))
  29.699 +		plover_vector_append(tasked_packages,name);
  29.700 +	    else
  29.701 +		other_packages=TRUE;
  29.702 +	}
  29.703 +    }
  29.704 +    if (!tasked_packages->len)
  29.705 +    {
  29.706 +	/*
  29.707 +	 * If there are no reportable packages tasked for action there
  29.708 +	 * shouldn't by any packages at all, but let's be paranoid.
  29.709 +	 */
  29.710 +	other_packages=FALSE;
  29.711 +	razor_install_iterator_rewind(ii);
  29.712 +	while (razor_install_iterator_next(ii,&package,&action,&count))
  29.713 +	{
  29.714 +	    if (action==report_action)
  29.715 +	    {
  29.716 +		razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
  29.717 +		  RAZOR_DETAIL_LAST);
  29.718 +		plover_vector_append(tasked_packages,name);
  29.719 +	    }
  29.720 +	}
  29.721 +    }
  29.722 +    if (!tasked_packages->len)
  29.723 +    {
  29.724 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  29.725 +	  PLOVER_GENERAL_ERROR_NO_WORK,"Transaction includes no %s actions",
  29.726 +	  report_action==RAZOR_INSTALL_ACTION_ADD?"add":"remove");
  29.727 +	plover_vector_free(tasked_packages);
  29.728 +	return FALSE;
  29.729 +    }
  29.730 +    if (!helper->transactions)
  29.731 +	plover_transaction_helper_check_vendor(helper,error);
  29.732 +    g_object_ref(transaction);
  29.733 +    helper->transactions=g_slist_append(helper->transactions,transaction);
  29.734 +    if (report_action==RAZOR_INSTALL_ACTION_ADD)
  29.735 +    {
  29.736 +	for(i=0;i<tasked_packages->len;i++)
  29.737 +	{
  29.738 +	    s=tasked_packages->strings[i];
  29.739 +	    if (!plover_vector_contains(helper->report_adding,s))
  29.740 +		plover_vector_append(helper->report_adding,s);
  29.741 +	}
  29.742 +	helper->report_adding_dependencies|=other_packages;
  29.743 +    }
  29.744 +    else
  29.745 +    {
  29.746 +	for(i=0;i<tasked_packages->len;i++)
  29.747 +	{
  29.748 +	    s=tasked_packages->strings[i];
  29.749 +	    if (!plover_vector_contains(helper->report_removing,s))
  29.750 +		plover_vector_append(helper->report_removing,s);
  29.751 +	}
  29.752 +	helper->report_removing_dependants|=other_packages;
  29.753 +    }
  29.754 +    plover_vector_free(tasked_packages);
  29.755 +    return TRUE;
  29.756 +}
  29.757 +
  29.758 +static PloverTransaction *
  29.759 +  plover_transaction_helper_new_transaction(PloverTransactionHelper *helper,
  29.760 +  GError **error)
  29.761 +{
  29.762 +    gboolean ok;
  29.763 +    const char *base,*prefix;
  29.764 +    GError *tmp_error=NULL;
  29.765 +    PloverTransaction *transaction;
  29.766 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
  29.767 +    prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
  29.768 +    if (tmp_error)
  29.769 +    {
  29.770 +	g_propagate_error(error,tmp_error);
  29.771 +	return NULL;
  29.772 +    }
  29.773 +    transaction=plover_transaction_new();
  29.774 +    plover_transaction_set_prefix(transaction,prefix);
  29.775 +    plover_transaction_set_installed(transaction,helper->installed);
  29.776 +    if (helper->upstream)
  29.777 +	ok=plover_transaction_set_upstream(transaction,helper->upstream,error);
  29.778 +    else
  29.779 +    {
  29.780 +	base=plover_transaction_helper_get_base(helper);
  29.781 +	ok=plover_transaction_set_upstream_from_yum(transaction,base,error);
  29.782 +    }
  29.783 +    if (!ok)
  29.784 +    {
  29.785 +	g_object_unref(transaction);
  29.786 +	transaction=NULL;
  29.787 +    }
  29.788 +    return transaction;
  29.789 +}
  29.790 +
  29.791 +struct plover_vector *plover_transaction_helper_group_get_default_packages(
  29.792 +  PloverTransactionHelper *helper,const char *group,GError **error)
  29.793 +{
  29.794 +    gboolean changed;
  29.795 +    struct comps *comps;
  29.796 +    struct comps_group *grp;
  29.797 +    struct comps_requirement *pkg;
  29.798 +    struct plover_vector *default_packages;
  29.799 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.800 +    comps=plover_transaction_helper_get_comps(helper,error);
  29.801 +    if (!comps)
  29.802 +	return NULL;
  29.803 +    grp=plover_comps_lookup_group(comps,group);
  29.804 +    if (!grp)
  29.805 +    {
  29.806 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  29.807 +	  PLOVER_GENERAL_ERROR_FAILED,"%s: group not found",group);
  29.808 +	return NULL;
  29.809 +    }
  29.810 +    default_packages=plover_vector_new();
  29.811 +    do
  29.812 +    {
  29.813 +	changed=FALSE;
  29.814 +	for(pkg=grp->packages;pkg;pkg=pkg->next)
  29.815 +	{
  29.816 +	    if (plover_vector_contains(default_packages,pkg->name))
  29.817 +		continue;
  29.818 +	    if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
  29.819 +	      pkg->type==COMPS_REQUIREMENT_MANDATORY ||
  29.820 +	      pkg->type==COMPS_REQUIREMENT_CONDITIONAL &&
  29.821 +	      plover_vector_contains(default_packages,pkg->requires))
  29.822 +	    {
  29.823 +		changed=TRUE;
  29.824 +		plover_vector_append(default_packages,pkg->name);
  29.825 +	    }
  29.826 +	}
  29.827 +    } while(changed);
  29.828 +    return default_packages;
  29.829 +}
  29.830 +
  29.831 +/*
  29.832 + * Returns TRUE if there is work to be done or FALSE if the packages are
  29.833 + * already installed or on error.
  29.834 + */
  29.835 +gboolean
  29.836 +  plover_transaction_helper_install_packages(PloverTransactionHelper *helper,
  29.837 +  struct plover_vector *packages,GError **error)
  29.838 +{
  29.839 +    gboolean retval;
  29.840 +    PloverTransaction *transaction;
  29.841 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.842 +    g_return_val_if_fail(packages != NULL,FALSE);
  29.843 +    if (!packages->len)
  29.844 +    {
  29.845 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  29.846 +	  PLOVER_GENERAL_ERROR_NO_WORK,"No packages listed to be installed");
  29.847 +	return FALSE;
  29.848 +    }
  29.849 +    transaction=plover_transaction_helper_new_transaction(helper,error);
  29.850 +    if (!transaction)
  29.851 +	return FALSE;
  29.852 +    if (!plover_transaction_install(transaction,packages->strings,error))
  29.853 +    {
  29.854 +	g_object_unref(transaction);
  29.855 +	return FALSE;
  29.856 +    }
  29.857 +    retval=plover_transaction_helper_add_transaction(helper,transaction,
  29.858 +      packages,RAZOR_INSTALL_ACTION_ADD,error);
  29.859 +    g_object_unref(transaction);
  29.860 +    return retval;
  29.861 +}
  29.862 +
  29.863 +/*
  29.864 + * Returns TRUE if there is work to be done or FALSE if the group is
  29.865 + * already installed or on error.
  29.866 + */
  29.867 +gboolean
  29.868 +  plover_transaction_helper_install_group(PloverTransactionHelper *helper,
  29.869 +  const char *group,GError **error)
  29.870 +{
  29.871 +    gboolean retval;
  29.872 +    struct plover_vector *selected_packages;
  29.873 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.874 +    selected_packages=plover_transaction_helper_group_get_default_packages(
  29.875 +      helper,group,error);
  29.876 +    if (!selected_packages)
  29.877 +	return FALSE;
  29.878 +    if (!selected_packages->len)
  29.879 +    {
  29.880 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  29.881 +	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
  29.882 +	plover_vector_free(selected_packages);
  29.883 +	return FALSE;
  29.884 +    }
  29.885 +    retval=plover_transaction_helper_install_packages(helper,selected_packages,
  29.886 +      error);
  29.887 +    plover_vector_free(selected_packages);
  29.888 +    return retval;
  29.889 +}
  29.890 +
  29.891 +/*
  29.892 + * Returns TRUE if there is work to be done or FALSE if the group is
  29.893 + * not installed or on error.
  29.894 + */
  29.895 +gboolean plover_transaction_helper_remove_group(PloverTransactionHelper *helper,
  29.896 +  const char *group,GError **error)
  29.897 +{
  29.898 +    gboolean retval;
  29.899 +    struct plover_vector *selected_packages;
  29.900 +    PloverTransaction *transaction;
  29.901 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.902 +    selected_packages=plover_transaction_helper_group_get_default_packages(
  29.903 +      helper,group,error);
  29.904 +    if (!selected_packages)
  29.905 +	return FALSE;
  29.906 +    if (!selected_packages->len)
  29.907 +    {
  29.908 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  29.909 +	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
  29.910 +	plover_vector_free(selected_packages);
  29.911 +	return FALSE;
  29.912 +    }
  29.913 +    transaction=plover_transaction_new();
  29.914 +    plover_transaction_set_installed(transaction,helper->installed);
  29.915 +    if (!plover_transaction_remove(transaction,selected_packages->strings,
  29.916 +      error))
  29.917 +    {
  29.918 +	plover_vector_free(selected_packages);
  29.919 +	g_object_unref(transaction);
  29.920 +	return FALSE;
  29.921 +    }
  29.922 +    retval=plover_transaction_helper_add_transaction(helper,transaction,
  29.923 +      NULL,RAZOR_INSTALL_ACTION_REMOVE,error);
  29.924 +    g_object_unref(transaction);
  29.925 +    plover_vector_free(selected_packages);
  29.926 +    return retval;
  29.927 +}
  29.928 +
  29.929 +/*
  29.930 + * Returns TRUE if there is work to be done or FALSE if all updates have
  29.931 + * already been applied or on error.
  29.932 + */
  29.933 +gboolean plover_transaction_helper_update(PloverTransactionHelper *helper,
  29.934 +  GError **error)
  29.935 +{
  29.936 +    gboolean retval;
  29.937 +    PloverTransaction *transaction;
  29.938 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.939 +    transaction=plover_transaction_helper_new_transaction(helper,error);
  29.940 +    if (!transaction)
  29.941 +	return FALSE;
  29.942 +    if (!plover_transaction_update(transaction,NULL,error))
  29.943 +    {
  29.944 +	g_object_unref(transaction);
  29.945 +	return FALSE;
  29.946 +    }
  29.947 +    retval=plover_transaction_helper_add_transaction(helper,transaction,
  29.948 +      NULL,RAZOR_INSTALL_ACTION_ADD,error);
  29.949 +    g_object_unref(transaction);
  29.950 +    return retval;
  29.951 +}
  29.952 +
  29.953 +gboolean plover_transaction_helper_get_visible(PloverTransactionHelper *helper)
  29.954 +{
  29.955 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
  29.956 +    if (helper->error_dialog)
  29.957 +	return TRUE;
  29.958 +    else if (!helper->assistant)
  29.959 +	return FALSE;
  29.960 +    else
  29.961 +	return gtk_widget_get_visible(GTK_WIDGET(helper->assistant));
  29.962 +}
  29.963 +
  29.964 +void plover_transaction_helper_present(PloverTransactionHelper *helper)
  29.965 +{
  29.966 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.967 +    if (helper->error_dialog)
  29.968 +	gtk_window_present(GTK_WINDOW(helper->error_dialog));
  29.969 +    else if (helper->assistant)
  29.970 +	gtk_window_present(GTK_WINDOW(helper->assistant));
  29.971 +}
  29.972 +
  29.973 +static void
  29.974 +  plover_transaction_helper_error_dialog_response(GtkDialog *error_dialog,
  29.975 +  int response_id,PloverTransactionHelper *helper)
  29.976 +{
  29.977 +    g_signal_handlers_disconnect_by_data(error_dialog,helper);
  29.978 +    if ((GtkWidget *)error_dialog==helper->error_dialog)
  29.979 +    {
  29.980 +	gtk_widget_destroy(helper->error_dialog);
  29.981 +	helper->error_dialog=NULL;
  29.982 +	if (helper->assistant)
  29.983 +	{
  29.984 +	    gtk_widget_hide(GTK_WIDGET(helper->assistant));
  29.985 +	    gtk_assistant_set_current_page(helper->assistant,0);
  29.986 +	}
  29.987 +	g_signal_emit(helper,signals[CLOSE],0);
  29.988 +    }
  29.989 +}
  29.990 +
  29.991 +const char *plover_transaction_helper_get_error(PloverTransactionHelper *helper,
  29.992 +  const GError **error)
  29.993 +{
  29.994 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
  29.995 +    if (!helper->error_dialog)
  29.996 +	return NULL;
  29.997 +    if (error)
  29.998 +	*error=helper->error;
  29.999 +    return helper->error_primary_text;
 29.1000 +}
 29.1001 +
 29.1002 +void plover_transaction_helper_set_error(PloverTransactionHelper *helper,
 29.1003 +  const GError *error,const char *primary_text)
 29.1004 +{
 29.1005 +    GtkMessageType type;
 29.1006 +    GtkWindow *window;
 29.1007 +    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
 29.1008 +    g_return_if_fail(error != NULL);
 29.1009 +    g_return_if_fail(primary_text != NULL);
 29.1010 +    if (helper->pulse_handler)
 29.1011 +    {
 29.1012 +	g_source_remove(helper->pulse_handler);
 29.1013 +	helper->pulse_handler=0;
 29.1014 +    }
 29.1015 +    if (helper->error_dialog)
 29.1016 +    {
 29.1017 +	gtk_widget_destroy(helper->error_dialog);
 29.1018 +	helper->error_dialog=NULL;
 29.1019 +    }
 29.1020 +    g_free(helper->error_primary_text);
 29.1021 +    helper->error_primary_text=g_strdup(primary_text);
 29.1022 +    g_clear_error(&helper->error);
 29.1023 +    helper->error=g_error_copy(error);
 29.1024 +    if (g_error_matches(error,PLOVER_GENERAL_ERROR,
 29.1025 +      PLOVER_GENERAL_ERROR_NO_WORK))
 29.1026 +	type=GTK_MESSAGE_INFO;
 29.1027 +    else
 29.1028 +	type=GTK_MESSAGE_ERROR;
 29.1029 +    if (helper->assistant)
 29.1030 +	window=GTK_WINDOW(helper->assistant);
 29.1031 +    else
 29.1032 +    	window=NULL;
 29.1033 +    helper->error_dialog=gtk_message_dialog_new(window,
 29.1034 +      GTK_DIALOG_DESTROY_WITH_PARENT,type,GTK_BUTTONS_CLOSE,primary_text);
 29.1035 +    gtk_message_dialog_format_secondary_text(
 29.1036 +      GTK_MESSAGE_DIALOG(helper->error_dialog),error->message);
 29.1037 +    gtk_widget_show(helper->error_dialog);
 29.1038 +    g_signal_connect(helper->error_dialog,"response",
 29.1039 +      G_CALLBACK(plover_transaction_helper_error_dialog_response),helper);
 29.1040 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/plover-gtk/transactionhelper.h	Sat Nov 15 19:04:45 2014 +0000
    30.3 @@ -0,0 +1,102 @@
    30.4 +#ifndef __PLOVER_TRANSACTION_HELPER_H__
    30.5 +#define __PLOVER_TRANSACTION_HELPER_H__
    30.6 +
    30.7 +#include <gtk/gtk.h>
    30.8 +#include <plover/packageset.h>
    30.9 +#include <plover/repository.h>
   30.10 +#include <plover/transaction.h>
   30.11 +
   30.12 +#define PLOVER_TYPE_TRANSACTION_HELPER	plover_transaction_helper_get_type()
   30.13 +#define PLOVER_TRANSACTION_HELPER(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   30.14 +					  PLOVER_TYPE_TRANSACTION_HELPER,\
   30.15 +					  PloverTransactionHelper)
   30.16 +#define PLOVER_TRANSACTION_HELPER_CLASS(klass) \
   30.17 +					G_TYPE_CHECK_CLASS_CAST(klass,\
   30.18 +					  PLOVER_TYPE_TRANSACTION_HELPER,\
   30.19 +					  PloverTransactionHelperClass)
   30.20 +#define PLOVER_IS_TRANSACTION_HELPER(obj) \
   30.21 +					G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   30.22 +					  PLOVER_TYPE_TRANSACTION_HELPER)
   30.23 +#define PLOVER_IS_TRANSACTION_HELPER_CLASS(klass) \
   30.24 +					G_TYPE_CHECK_CLASS_TYPE(obj,\
   30.25 +					  PLOVER_TYPE_TRANSACTION_HELPER)
   30.26 +#define PLOVER_TRANSACTION_HELPER_GET_CLASS(obj) \
   30.27 +					G_TYPE_INSTANCE_GET_CLASS(obj,\
   30.28 +					  PLOVER_TYPE_TRANSACTION_HELPER,\
   30.29 +					  PloverTransactionHelperClass)
   30.30 +
   30.31 +typedef struct _PloverTransactionHelper {
   30.32 +    GObject parent_instance;
   30.33 +    PloverPackageSet *installed;
   30.34 +    PloverRepository *upstream;
   30.35 +    PloverPackageSet *relocated_upstream;
   30.36 +    gchar *base;
   30.37 +    gchar *unsatisfied;
   30.38 +    struct comps *comps;
   30.39 +    gboolean check_vendor;
   30.40 +    gboolean report_adding_dependencies;
   30.41 +    gboolean report_removing_dependants;
   30.42 +    struct plover_vector *report_adding,*report_removing;
   30.43 +    GSList *transactions;
   30.44 +    GtkBuilder *ui;
   30.45 +    GtkAssistant *assistant;
   30.46 +    guint pulse_handler;
   30.47 +    GError *error;
   30.48 +    gchar *error_primary_text;
   30.49 +    GtkWidget *error_dialog;
   30.50 +} PloverTransactionHelper;
   30.51 +
   30.52 +typedef struct _PloverTransactionHelperClass {
   30.53 +    GObjectClass parent_class;
   30.54 +} PloverTransactionHelperClass;
   30.55 +
   30.56 +GType plover_transaction_helper_get_type(void);
   30.57 +PloverTransactionHelper *plover_transaction_helper_new(GtkBuilder *ui);
   30.58 +PloverPackageSet *
   30.59 +  plover_transaction_helper_get_installed(PloverTransactionHelper *helper);
   30.60 +void plover_transaction_helper_set_installed(PloverTransactionHelper *helper,
   30.61 +  PloverPackageSet *installed);
   30.62 +PloverRepository *
   30.63 +  plover_transaction_helper_get_upstream(PloverTransactionHelper *helper,
   30.64 +  GError **error);
   30.65 +void plover_transaction_helper_set_upstream(PloverTransactionHelper *helper,
   30.66 +  PloverRepository *upstream);
   30.67 +const char *plover_transaction_helper_get_base(PloverTransactionHelper *helper);
   30.68 +void plover_transaction_helper_set_base(PloverTransactionHelper *helper,
   30.69 +  const char *base);
   30.70 +struct comps *
   30.71 +  plover_transaction_helper_get_comps(PloverTransactionHelper *helper,
   30.72 +  GError **error);
   30.73 +const char *
   30.74 +  plover_transaction_helper_get_prefix(PloverTransactionHelper *helper,
   30.75 +  GError **error);
   30.76 +void plover_transaction_helper_set_check_vendor(PloverTransactionHelper *helper,
   30.77 +  gboolean check_vendor);
   30.78 +const char *
   30.79 +  plover_transaction_helper_get_unsatisfied(PloverTransactionHelper *helper);
   30.80 +gboolean
   30.81 +  plover_transaction_helper_add_transaction(PloverTransactionHelper *helper,
   30.82 +  PloverTransaction *transaction,struct plover_vector *report_packages,
   30.83 +  enum razor_install_action report_action,GError **error);
   30.84 +struct plover_vector *plover_transaction_helper_group_get_default_packages(
   30.85 +  PloverTransactionHelper *helper,const char *group,GError **error);
   30.86 +gboolean
   30.87 +  plover_transaction_helper_install_packages(PloverTransactionHelper *helper,
   30.88 +  struct plover_vector *packages,GError **error);
   30.89 +gboolean
   30.90 +  plover_transaction_helper_install_group(PloverTransactionHelper *helper,
   30.91 +  const char *group,GError **error);
   30.92 +gboolean
   30.93 +  plover_transaction_helper_remove_group(PloverTransactionHelper *helper,
   30.94 +  const char *group,GError **error);
   30.95 +gboolean
   30.96 +  plover_transaction_helper_update(PloverTransactionHelper *helper,
   30.97 +  GError **error);
   30.98 +gboolean plover_transaction_helper_get_visible(PloverTransactionHelper *helper);
   30.99 +void plover_transaction_helper_present(PloverTransactionHelper *helper);
  30.100 +const char *plover_transaction_helper_get_error(PloverTransactionHelper *helper,
  30.101 +  const GError **error);
  30.102 +void plover_transaction_helper_set_error(PloverTransactionHelper *helper,
  30.103 +  const GError *error,const char *primary_text);
  30.104 +
  30.105 +#endif /* __PLOVER_TRANSACTION_HELPER_H__ */
    31.1 --- a/plover/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
    31.2 +++ b/plover/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
    31.3 @@ -3,10 +3,11 @@
    31.4  INCLUDES=-I$(top_srcdir)
    31.5  AM_LDFLAGS=-no-undefined -version-info $(LIBPLOVER_LT_VERSION_INFO)
    31.6  
    31.7 -pkginclude_HEADERS=plover.h
    31.8 +pkginclude_HEADERS=plover.h transaction.h package.h packageset.h repository.h
    31.9  
   31.10  lib_LTLIBRARIES=libplover.la
   31.11 -libplover_la_SOURCES=$(pkginclude_HEADERS) util.c import-yum.c razor.c comps.c
   31.12 +libplover_la_SOURCES=$(pkginclude_HEADERS) util.c import-yum.c razor.c comps.c \
   31.13 +	log.c vector.c transaction.c package.c packageset.c repository.c
   31.14  
   31.15  pkgconfigdir=$(libdir)/pkgconfig
   31.16  pkgconfig_DATA=plover.pc
    32.1 --- a/plover/import-yum.c	Fri Mar 23 20:29:50 2012 +0000
    32.2 +++ b/plover/import-yum.c	Sat Nov 15 19:04:45 2014 +0000
    32.3 @@ -1,7 +1,7 @@
    32.4  /*
    32.5   * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    32.6   * Copyright (C) 2008  Red Hat, Inc
    32.7 - * Copyright (C) 2009, 2011  J. Ali Harlow <ali@juiblex.co.uk>
    32.8 + * Copyright (C) 2009, 2011, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    32.9   *
   32.10   * This program is free software; you can redistribute it and/or modify
   32.11   * it under the terms of the GNU General Public License as published by
   32.12 @@ -28,6 +28,7 @@
   32.13  #include <fcntl.h>
   32.14  #include <errno.h>
   32.15  
   32.16 +#include <glib.h>
   32.17  #include <expat.h>
   32.18  #include <zlib.h>
   32.19  #include <razor.h>
   32.20 @@ -306,94 +307,110 @@
   32.21  
   32.22  #define XML_BUFFER_SIZE 4096
   32.23  
   32.24 -struct razor_set *
   32.25 -plover_razor_set_create_from_yum(const char *base)
   32.26 +struct razor_set *plover_razor_set_create_from_yum(const char *base,
   32.27 +  GError **error)
   32.28  {
   32.29 -	struct yum_context ctx;
   32.30 -	void *buf;
   32.31 -	int len;
   32.32 -	gzFile primary, filelists;
   32.33 -	XML_ParsingStatus status;
   32.34 -	struct razor_set *set;
   32.35 -
   32.36 -	ctx.importer = razor_importer_create();
   32.37 -	ctx.state = YUM_STATE_BEGIN;
   32.38 -
   32.39 -	ctx.primary_parser = XML_ParserCreate(NULL);
   32.40 -	XML_SetUserData(ctx.primary_parser, &ctx);
   32.41 -	XML_SetElementHandler(ctx.primary_parser,
   32.42 -			      yum_primary_start_element,
   32.43 -			      yum_primary_end_element);
   32.44 -	XML_SetCharacterDataHandler(ctx.primary_parser,
   32.45 -				    yum_character_data);
   32.46 -
   32.47 -	ctx.filelists_parser = XML_ParserCreate(NULL);
   32.48 -	XML_SetUserData(ctx.filelists_parser, &ctx);
   32.49 -	XML_SetElementHandler(ctx.filelists_parser,
   32.50 -			      yum_filelists_start_element,
   32.51 -			      yum_filelists_end_element);
   32.52 -	XML_SetCharacterDataHandler(ctx.filelists_parser,
   32.53 -				    yum_character_data);
   32.54 -
   32.55 -	primary = gzopen("primary.xml.gz", "rb");
   32.56 -	if (primary == NULL)
   32.57 -		return NULL;
   32.58 -	filelists = gzopen("filelists.xml.gz", "rb");
   32.59 -	if (filelists == NULL)
   32.60 -		return NULL;
   32.61 -
   32.62 -	ctx.current_parser = ctx.primary_parser;
   32.63 -
   32.64 -	ctx.current = 0;
   32.65 -
   32.66 -	do {
   32.67 -		XML_GetParsingStatus(ctx.current_parser, &status);
   32.68 -		switch (status.parsing) {
   32.69 -		case XML_SUSPENDED:
   32.70 -			XML_ResumeParser(ctx.current_parser);
   32.71 -			break;
   32.72 -		case XML_PARSING:
   32.73 -		case XML_INITIALIZED:
   32.74 -			buf = XML_GetBuffer(ctx.current_parser,
   32.75 -					    XML_BUFFER_SIZE);
   32.76 -			if (ctx.current_parser == ctx.primary_parser)
   32.77 -				len = gzread(primary, buf, XML_BUFFER_SIZE);
   32.78 -			else
   32.79 -				len = gzread(filelists, buf, XML_BUFFER_SIZE);
   32.80 -			if (len < 0) {
   32.81 -				fprintf(stderr,
   32.82 -					"couldn't read input: %s\n",
   32.83 -					strerror(errno));
   32.84 -				return NULL;
   32.85 -			}
   32.86 -
   32.87 -			XML_ParseBuffer(ctx.current_parser, len, len == 0);
   32.88 -			break;
   32.89 -		case XML_FINISHED:
   32.90 -			break;
   32.91 +    struct yum_context ctx;
   32.92 +    gchar *s;
   32.93 +    void *buf;
   32.94 +    int len;
   32.95 +    gzFile primary, filelists;
   32.96 +    XML_ParsingStatus status;
   32.97 +    struct razor_set *set;
   32.98 +    int errnum;
   32.99 +    const char *errstr,*errobj;
  32.100 +    ctx.importer=razor_importer_create();
  32.101 +    ctx.state=YUM_STATE_BEGIN;
  32.102 +    ctx.primary_parser=XML_ParserCreate(NULL);
  32.103 +    XML_SetUserData(ctx.primary_parser,&ctx);
  32.104 +    XML_SetElementHandler(ctx.primary_parser,yum_primary_start_element,
  32.105 +      yum_primary_end_element);
  32.106 +    XML_SetCharacterDataHandler(ctx.primary_parser,yum_character_data);
  32.107 +    ctx.filelists_parser=XML_ParserCreate(NULL);
  32.108 +    XML_SetUserData(ctx.filelists_parser,&ctx);
  32.109 +    XML_SetElementHandler(ctx.filelists_parser,yum_filelists_start_element,
  32.110 +      yum_filelists_end_element);
  32.111 +    XML_SetCharacterDataHandler(ctx.filelists_parser,yum_character_data);
  32.112 +    errno=0;
  32.113 +    s=g_build_filename(base,"repodata","primary.xml.gz",NULL);
  32.114 +    primary=gzopen(s,"rb");
  32.115 +    if (!primary)
  32.116 +    {
  32.117 +	g_set_error(error,RAZOR_POSIX_ERROR,errno?errno:ENOMEM,
  32.118 +	  "%s: %s",s,strerror(errno));
  32.119 +	g_free(s);
  32.120 +	return NULL;
  32.121 +    }
  32.122 +    g_free(s);
  32.123 +    s=g_build_filename(base,"repodata","filelists.xml.gz",NULL);
  32.124 +    filelists=gzopen(s,"rb");
  32.125 +    if (!filelists)
  32.126 +    {
  32.127 +	g_set_error(error,RAZOR_POSIX_ERROR,errno?errno:ENOMEM,
  32.128 +	  "%s: %s",s,strerror(errno));
  32.129 +	g_free(s);
  32.130 +	return NULL;
  32.131 +    }
  32.132 +    g_free(s);
  32.133 +    ctx.current_parser=ctx.primary_parser;
  32.134 +    ctx.current=0;
  32.135 +    do
  32.136 +    {
  32.137 +	XML_GetParsingStatus(ctx.current_parser,&status);
  32.138 +	switch (status.parsing)
  32.139 +	{
  32.140 +	    case XML_SUSPENDED:
  32.141 +		XML_ResumeParser(ctx.current_parser);
  32.142 +		break;
  32.143 +	    case XML_PARSING:
  32.144 +	    case XML_INITIALIZED:
  32.145 +		buf=XML_GetBuffer(ctx.current_parser,XML_BUFFER_SIZE);
  32.146 +		if (ctx.current_parser==ctx.primary_parser)
  32.147 +		    len=gzread(primary,buf,XML_BUFFER_SIZE);
  32.148 +		else
  32.149 +		    len=gzread(filelists,buf,XML_BUFFER_SIZE);
  32.150 +		if (len<0)
  32.151 +		{
  32.152 +		    if (ctx.current_parser==ctx.primary_parser)
  32.153 +		    {
  32.154 +			errstr=gzerror(primary,&errnum);
  32.155 +			errobj="primary.xml.gz";
  32.156 +		    }
  32.157 +		    else
  32.158 +		    {
  32.159 +			errstr=gzerror(filelists,&errnum);
  32.160 +			errobj="filelists.xml.gz";
  32.161 +		    }
  32.162 +		    if (errnum==Z_ERRNO)
  32.163 +			g_set_error(error,PLOVER_POSIX_ERROR,errno,"%s: %s",
  32.164 +			  errobj,strerror(errno));
  32.165 +		    else
  32.166 +			g_set_error(error,RAZOR_ZLIB_ERROR,errnum,"%s: %s",
  32.167 +			  errobj,errstr);
  32.168 +		    return NULL;
  32.169  		}
  32.170 -	} while (status.parsing != XML_FINISHED);
  32.171 -
  32.172 -
  32.173 -	XML_ParserFree(ctx.primary_parser);
  32.174 -	XML_ParserFree(ctx.filelists_parser);
  32.175 -
  32.176 -	gzclose(primary);
  32.177 -	gzclose(filelists);
  32.178 -
  32.179 -	set = razor_importer_finish(ctx.importer);
  32.180 -#if RAZOR_HEADER_VERSION_MIN <= 1
  32.181 -	/*
  32.182 -	 * Header version 1 is supported by plover v0.3 and is used on
  32.183 -	 * 32-bit intel machines which allows the setup and update
  32.184 -	 * applications from v0.3 to work. On other machines, we don't
  32.185 -	 * want these old applications to work (since they would do
  32.186 -	 * the wrong thing) and so we use the current header version
  32.187 -	 * which they don't support.
  32.188 -	 */
  32.189 -	if (plover_system_arch_is_x86())
  32.190 -		razor_set_set_header_version(set, 1);
  32.191 +		XML_ParseBuffer(ctx.current_parser,len,!len);
  32.192 +		break;
  32.193 +	    case XML_FINISHED:
  32.194 +		break;
  32.195 +	}
  32.196 +    } while (status.parsing!=XML_FINISHED);
  32.197 +    XML_ParserFree(ctx.primary_parser);
  32.198 +    XML_ParserFree(ctx.filelists_parser);
  32.199 +    gzclose(primary);
  32.200 +    gzclose(filelists);
  32.201 +    set=razor_importer_finish(ctx.importer);
  32.202 +#if RAZOR_HEADER_VERSION_MIN<=1
  32.203 +    /*
  32.204 +     * Header version 1 is supported by plover v0.3 and is used on
  32.205 +     * 32-bit intel machines which allows the setup and update
  32.206 +     * applications from v0.3 to work. On other machines, we don't
  32.207 +     * want these old applications to work (since they would do
  32.208 +     * the wrong thing) and so we use the current header version
  32.209 +     * which they don't support.
  32.210 +     */
  32.211 +    if (plover_system_arch_is_x86())
  32.212 +	razor_set_set_header_version(set,1);
  32.213  #endif
  32.214 -
  32.215 -	return set;
  32.216 +    return set;
  32.217  }
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/plover/log.c	Sat Nov 15 19:04:45 2014 +0000
    33.3 @@ -0,0 +1,378 @@
    33.4 +/*
    33.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    33.6 + *
    33.7 + * This program is free software; you can redistribute it and/or modify
    33.8 + * it under the terms of the GNU General Public License as published by
    33.9 + * the Free Software Foundation; either version 2 of the License, or
   33.10 + * (at your option) any later version.
   33.11 + *
   33.12 + * This program is distributed in the hope that it will be useful,
   33.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 + * GNU General Public License for more details.
   33.16 + *
   33.17 + * You should have received a copy of the GNU General Public License along
   33.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   33.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   33.20 + */
   33.21 +
   33.22 +#include <stdlib.h>
   33.23 +#include <stddef.h>
   33.24 +#include <stdio.h>
   33.25 +#include <string.h>
   33.26 +#include <sys/types.h>
   33.27 +#include <sys/stat.h>
   33.28 +#include <unistd.h>
   33.29 +#include <time.h>
   33.30 +#include <errno.h>
   33.31 +#include <fcntl.h>
   33.32 +#ifdef WIN32
   33.33 +#include <windows.h>
   33.34 +#include <io.h>
   33.35 +#else
   33.36 +#include <dirent.h>
   33.37 +#endif
   33.38 +#include "config.h"
   33.39 +#include "plover.h"
   33.40 +
   33.41 +#ifndef FALSE
   33.42 +#define FALSE	0
   33.43 +#endif
   33.44 +
   33.45 +#ifndef TRUE
   33.46 +#define TRUE	(!FALSE)
   33.47 +#endif
   33.48 +
   33.49 +#define MAX_OLD_LOGFILES	4	/* (5 including the current) */
   33.50 +
   33.51 +#ifdef WIN32
   33.52 +
   33.53 +struct find_suffixed_data {
   33.54 +    HANDLE handle;
   33.55 +    WIN32_FIND_DATA wfd;
   33.56 +    int base_len;
   33.57 +    char *suffix;
   33.58 +};
   33.59 +
   33.60 +static int find_suffixed_first(const char *path,struct find_suffixed_data *data)
   33.61 +{
   33.62 +    const char *t1,*t2;
   33.63 +    gchar *s;
   33.64 +    s=g_strconcat(path,"-*",NULL);
   33.65 +    data->handle=FindFirstFile(s,&data->wfd);
   33.66 +    g_free(s);
   33.67 +    if (data->handle==INVALID_HANDLE_VALUE)
   33.68 +	return FALSE;
   33.69 +    t1=strrchr(path,'/');
   33.70 +    t2=strrchr(t1?t1:path,'\\');
   33.71 +    if (t2)
   33.72 +	data->base_len=strlen(t2+1);
   33.73 +    else if (t1)
   33.74 +	data->base_len=strlen(t1+1);
   33.75 +    else
   33.76 +	data->base_len=strlen(path);
   33.77 +    data->suffix=strdup(data->wfd.cFileName+data->base_len);
   33.78 +    return TRUE;
   33.79 +}
   33.80 +
   33.81 +static int find_suffixed_next(struct find_suffixed_data *data)
   33.82 +{
   33.83 +    if (!FindNextFile(data->handle,&data->wfd))
   33.84 +	return FALSE;
   33.85 +    free(data->suffix);
   33.86 +    data->suffix=strdup(data->wfd.cFileName+data->base_len);
   33.87 +    return TRUE;
   33.88 +}
   33.89 +
   33.90 +static void find_suffixed_close(struct find_suffixed_data *data)
   33.91 +{
   33.92 +    free(data->suffix);
   33.93 +    FindClose(data->handle);
   33.94 +}
   33.95 +
   33.96 +#else	/* WIN32 */
   33.97 +
   33.98 +struct find_suffixed_data {
   33.99 +    DIR *dir;
  33.100 +    struct dirent *entry;
  33.101 +    char *base;
  33.102 +    int base_len;
  33.103 +    char *suffix;
  33.104 +};
  33.105 +
  33.106 +static int find_suffixed_next(struct find_suffixed_data *data)
  33.107 +{
  33.108 +    struct dirent *entry_result;
  33.109 +    while (!readdir_r(data->dir,data->entry,&entry_result) && entry_result)
  33.110 +    {
  33.111 +	if (strncmp(data->entry->d_name,data->base,data->base_len) ||
  33.112 +	  data->entry->d_name[data->base_len]!='-')
  33.113 +	    continue;
  33.114 +	free(data->suffix);
  33.115 +	data->suffix=strdup(data->entry->d_name+data->base_len);
  33.116 +	return TRUE;
  33.117 +    }
  33.118 +    return FALSE;
  33.119 +}
  33.120 +
  33.121 +/*
  33.122 + * From http://womble.decadent.org.uk/readdir_r-advisory.html
  33.123 + *
  33.124 + * Calculate the required buffer size (in bytes) for directory
  33.125 + * entries read from the given directory handle. Return -1 if this
  33.126 + * this cannot be done.
  33.127 + *
  33.128 + * This code does not trust values of NAME_MAX that are less than
  33.129 + * 255, since some systems (including at least HP-UX) incorrectly
  33.130 + * define it to be a smaller value.
  33.131 + *
  33.132 + * If you use autoconf, include fpathconf and dirfd in your
  33.133 + * AC_CHECK_FUNCS list. Otherwise use some other method to detect
  33.134 + * and use them where available.
  33.135 + */
  33.136 +
  33.137 +static size_t dirent_buf_size(DIR * dirp)
  33.138 +{
  33.139 +    long name_max;
  33.140 +    size_t name_end;
  33.141 +#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX)
  33.142 +    name_max=fpathconf(dirfd(dirp),_PC_NAME_MAX);
  33.143 +    if (name_max==-1)
  33.144 +#if defined(NAME_MAX)
  33.145 +	name_max=(NAME_MAX>255)?NAME_MAX:255;
  33.146 +#else
  33.147 +	return (size_t)-1;
  33.148 +#endif	/* NAME_MAX */
  33.149 +#else
  33.150 +#if defined(NAME_MAX)
  33.151 +    name_max=(NAME_MAX>255)?NAME_MAX:255;
  33.152 +#else
  33.153 +#error "buffer size for readdir_r cannot be determined"
  33.154 +#endif	/* NAME_MAX */
  33.155 +#endif	/* HAVE_FPATHCONF && HAVE_DIRFD && _PC_NAME_MAX */
  33.156 +    name_end=(size_t)offsetof(struct dirent,d_name)+name_max+1;
  33.157 +    return (name_end>sizeof(struct dirent)?name_end:sizeof(struct dirent));
  33.158 +}
  33.159 +
  33.160 +static int find_suffixed_first(const char *path,struct find_suffixed_data *data)
  33.161 +{
  33.162 +    int len;
  33.163 +    char *s,*base;
  33.164 +    base=strrchr(path,'/');
  33.165 +    if (base)
  33.166 +    {
  33.167 +	if (base==path)
  33.168 +	    data->dir=opendir("/");
  33.169 +	else
  33.170 +	{
  33.171 +	    s=strndup(path,base-path);
  33.172 +	    data->dir=opendir(s);
  33.173 +	    free(s);
  33.174 +	}
  33.175 +	data->base=strdup(path+1);
  33.176 +    }
  33.177 +    else
  33.178 +    {
  33.179 +	data->dir=opendir(".");
  33.180 +	data->base=strdup(path);
  33.181 +    }
  33.182 +    if (!data->dir)
  33.183 +    {
  33.184 +	free(data->base);
  33.185 +	return FALSE;
  33.186 +    }
  33.187 +    data->base_len=strlen(data->base);
  33.188 +    len=dirent_buf_size(data->dir);
  33.189 +    if (len<0)
  33.190 +    {
  33.191 +	closedir(data->dir);
  33.192 +	return FALSE;
  33.193 +    }
  33.194 +    data->entry=malloc(len);
  33.195 +    if (!data->entry)
  33.196 +    {
  33.197 +	closedir(data->dir);
  33.198 +	return FALSE;
  33.199 +    }
  33.200 +    if (find_suffixed_next(data))
  33.201 +	return TRUE;
  33.202 +    free(data->entry);
  33.203 +    closedir(data->dir);
  33.204 +    return FALSE;
  33.205 +}
  33.206 +
  33.207 +static void find_suffixed_close(struct find_suffixed_data *data)
  33.208 +{
  33.209 +    free(data->suffix);
  33.210 +    free(data->entry);
  33.211 +    closedir(data->dir);
  33.212 +}
  33.213 +
  33.214 +#endif	/* WIN32 */
  33.215 +
  33.216 +static int prune_old_logfiles(const char *path)
  33.217 +{
  33.218 +    int i,n_suffixes;
  33.219 +    gchar *s;
  33.220 +    char *suffix,*suffixes[MAX_OLD_LOGFILES];
  33.221 +    struct find_suffixed_data fsd;
  33.222 +    if (find_suffixed_first(path,&fsd))
  33.223 +    {
  33.224 +	n_suffixes=0;
  33.225 +	do
  33.226 +	{
  33.227 +	    suffix=strdup(fsd.suffix);
  33.228 +	    if (n_suffixes<MAX_OLD_LOGFILES)
  33.229 +		suffixes[n_suffixes++]=suffix;
  33.230 +	    else
  33.231 +	    {
  33.232 +		for(i=0;i<MAX_OLD_LOGFILES;i++)
  33.233 +		    if (strcmp(suffix,suffixes[i])>0)
  33.234 +		    {
  33.235 +			s=suffixes[i];
  33.236 +			suffixes[i]=suffix;
  33.237 +			suffix=s;
  33.238 +		    }
  33.239 +		s=g_strconcat(path,suffix,NULL);
  33.240 +		(void)remove(s);
  33.241 +		g_free(s);
  33.242 +		free(suffix);
  33.243 +	    }
  33.244 +	} while(find_suffixed_next(&fsd));
  33.245 +	find_suffixed_close(&fsd);
  33.246 +	for(i=0;i<n_suffixes;i++)
  33.247 +	    free(suffixes[i]);
  33.248 +    }
  33.249 +    return 0;
  33.250 +}
  33.251 +
  33.252 +static int rotate_logfile(const char *path,struct tm *modified)
  33.253 +{
  33.254 +    gchar *s;
  33.255 +    char serial;
  33.256 +    char suffix[11];			/* -yyyymmdd or -yyyymmdds */
  33.257 +    sprintf(suffix,"-%04d%02d%02d",modified->tm_year+1900,modified->tm_mon+1,
  33.258 +      modified->tm_mday);
  33.259 +    s=g_strconcat(path,suffix,NULL);
  33.260 +    if (rename(path,s))
  33.261 +    {
  33.262 +	suffix[10]='\0';
  33.263 +	for(serial='a';serial<='z';serial++)
  33.264 +	{
  33.265 +	    if (errno!=EACCES || serial=='z')
  33.266 +	    {
  33.267 +		perror(s);
  33.268 +		free(s);
  33.269 +		return -1;
  33.270 +	    }
  33.271 +	    free(s);
  33.272 +	    suffix[9]=serial;
  33.273 +	    s=g_strconcat(path,suffix,NULL);
  33.274 +	    if (!rename(path,s))
  33.275 +		break;
  33.276 +	}
  33.277 +    }
  33.278 +    g_free(s);
  33.279 +    return prune_old_logfiles(path);
  33.280 +}
  33.281 +
  33.282 +int plover_log_open(const char *path)
  33.283 +{
  33.284 +    int retval;
  33.285 +    char *root;
  33.286 +    gchar *filename;
  33.287 +    struct stat sb;
  33.288 +    time_t t;
  33.289 +    struct tm today,modified;
  33.290 +    struct razor_atomic *atomic;
  33.291 +    FILE *fp;
  33.292 +    root=getenv("RAZOR_ROOT");
  33.293 +    if (root)
  33.294 +	filename=g_strconcat(root,path,NULL);
  33.295 +    else
  33.296 +	filename=g_strdup(path);
  33.297 +    atomic=razor_atomic_open("Open log");
  33.298 +    razor_atomic_make_dirs(atomic,"",filename);
  33.299 +    retval=razor_atomic_commit(atomic);
  33.300 +    if (retval)
  33.301 +	fprintf(stderr,"Can't open log: %s\n",
  33.302 +	  razor_atomic_get_error_msg(atomic));
  33.303 +    razor_atomic_destroy(atomic);
  33.304 +    if (retval)
  33.305 +	return retval;
  33.306 +    if (stat(filename,&sb)<0)
  33.307 +    {
  33.308 +	if (errno!=ENOENT)
  33.309 +	{
  33.310 +	    fprintf(stderr,"Can't open log: ");
  33.311 +	    perror(filename);
  33.312 +	    g_free(filename);
  33.313 +	    return -1;
  33.314 +	}
  33.315 +    }
  33.316 +    else if (!S_ISREG(sb.st_mode))
  33.317 +    {
  33.318 +	fprintf(stderr,"Can't open log: %s: Not a regular file\n",filename);
  33.319 +	g_free(filename);
  33.320 +	return -1;
  33.321 +    }
  33.322 +    else
  33.323 +    {
  33.324 +	time(&t);
  33.325 +#ifdef WIN32
  33.326 +	localtime_s(&today,&t);
  33.327 +	localtime_s(&modified,&sb.st_mtime);
  33.328 +#else
  33.329 +	localtime_r(&t,&today);
  33.330 +	localtime_r(&sb.st_mtime,&modified);
  33.331 +#endif
  33.332 +	if (modified.tm_yday!=today.tm_yday || modified.tm_year!=today.tm_year)
  33.333 +	    rotate_logfile(filename,&modified);
  33.334 +    }
  33.335 +    fp=fopen(filename,"a");
  33.336 +    if (!fp)
  33.337 +    {
  33.338 +	fprintf(stderr,"Can't open log: ");
  33.339 +	perror(filename);
  33.340 +	g_free(filename);
  33.341 +	return -1;
  33.342 +    }
  33.343 +    g_free(filename);
  33.344 +#ifdef WIN32
  33.345 +    /*
  33.346 +     * The situation under MS-Windows is a little complicated. If standard
  33.347 +     * output and standard error are valid then the normal code will work.
  33.348 +     * This applies in console applications and even in GUI applications
  33.349 +     * if standard output and standard error are redirected by the parent
  33.350 +     * process (eg., by cmd.exe). However GUI applications started in
  33.351 +     * typical fashion will have invalid standard output and standard error.
  33.352 +     * See http://support.microsoft.com/kb/105305 for some more detail.
  33.353 +     * NB: This solution assumes that fd 1 and 2 are either used for
  33.354 +     * standard output/error or are unused.
  33.355 +     */
  33.356 +    fclose(stdout);
  33.357 +    fclose(stderr);
  33.358 +#else
  33.359 +    fflush(stdout);
  33.360 +    fflush(stderr);
  33.361 +#endif
  33.362 +    if (dup2(fileno(fp),1)<0 || dup2(fileno(fp),2)<0)
  33.363 +    {
  33.364 +	perror("Failed to redirect standard error/output");
  33.365 +	fclose(fp);
  33.366 +	return -1;
  33.367 +    }
  33.368 +    fclose(fp);
  33.369 +#ifdef WIN32
  33.370 +    *stdout=*fdopen(1,"a");
  33.371 +    setvbuf(stdout,NULL,_IONBF,0);
  33.372 +    *stderr=*fdopen(2,"a");
  33.373 +    setvbuf(stderr,NULL,_IONBF,0);
  33.374 +    SetStdHandle(STD_OUTPUT_HANDLE,(HANDLE)_get_osfhandle(1));
  33.375 +    SetStdHandle(STD_ERROR_HANDLE,(HANDLE)_get_osfhandle(2));
  33.376 +#endif
  33.377 +    time(&t);
  33.378 +    printf("Run started on %s",ctime(&t));
  33.379 +    fflush(stdout);
  33.380 +    return 0;
  33.381 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/plover/package.c	Sat Nov 15 19:04:45 2014 +0000
    34.3 @@ -0,0 +1,274 @@
    34.4 +/*
    34.5 + * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
    34.6 + *
    34.7 + * This program is free software; you can redistribute it and/or modify
    34.8 + * it under the terms of the GNU General Public License as published by
    34.9 + * the Free Software Foundation; either version 2 of the License, or
   34.10 + * (at your option) any later version.
   34.11 + *
   34.12 + * This program is distributed in the hope that it will be useful,
   34.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.15 + * GNU General Public License for more details.
   34.16 + *
   34.17 + * You should have received a copy of the GNU General Public License along
   34.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   34.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   34.20 + */
   34.21 +
   34.22 +#include "config.h"
   34.23 +#include <stdlib.h>
   34.24 +#include <string.h>
   34.25 +#include <glib-object.h>
   34.26 +#include <razor.h>
   34.27 +#include "plover/package.h"
   34.28 +
   34.29 +G_DEFINE_TYPE(PloverPackage,plover_package,G_TYPE_OBJECT);
   34.30 +
   34.31 +typedef struct _PloverPackagePrivate {
   34.32 +    struct razor_set *set;
   34.33 +    struct razor_package *pkg;
   34.34 +    GObject *file_store;
   34.35 +    const char **prefixes;
   34.36 +} PloverPackagePrivate;
   34.37 +
   34.38 +#define PLOVER_PACKAGE_GET_PRIVATE(obj)\
   34.39 +				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
   34.40 +				  PLOVER_TYPE_PACKAGE,PloverPackagePrivate)
   34.41 +
   34.42 +enum {
   34.43 +    CHANGED=0,
   34.44 +    N_SIGNALS
   34.45 +};
   34.46 +
   34.47 +static guint signals[N_SIGNALS];
   34.48 +
   34.49 +static void plover_package_finalize(GObject *obj)
   34.50 +{
   34.51 +    PloverPackagePrivate *priv=PLOVER_PACKAGE_GET_PRIVATE(obj);
   34.52 +    g_free(priv->prefixes);
   34.53 +    G_OBJECT_CLASS(plover_package_parent_class)->finalize(obj);
   34.54 +}
   34.55 +
   34.56 +static void plover_package_dispose(GObject *obj)
   34.57 +{
   34.58 +    PloverPackagePrivate *priv=PLOVER_PACKAGE_GET_PRIVATE(obj);
   34.59 +    if (priv->file_store)
   34.60 +    {
   34.61 +	g_object_unref(priv->file_store);
   34.62 +	priv->file_store=NULL;
   34.63 +    }
   34.64 +    G_OBJECT_CLASS(plover_package_parent_class)->dispose(obj);
   34.65 +}
   34.66 +
   34.67 +static void plover_package_class_init(PloverPackageClass *klass)
   34.68 +{
   34.69 +    GObjectClass *oclass=G_OBJECT_CLASS(klass);
   34.70 +    oclass->finalize=plover_package_finalize;
   34.71 +    oclass->dispose=plover_package_dispose;
   34.72 +    g_type_class_add_private(klass,sizeof(PloverPackagePrivate));
   34.73 +    signals[CHANGED]=g_signal_newv("changed",
   34.74 +      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
   34.75 +      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
   34.76 +}
   34.77 +
   34.78 +static void plover_package_init(PloverPackage *package)
   34.79 +{
   34.80 +}
   34.81 +
   34.82 +PloverPackage *plover_package_new(struct razor_set *set,
   34.83 +  struct razor_package *pkg)
   34.84 +{
   34.85 +    PloverPackage *package;
   34.86 +    PloverPackagePrivate *priv;
   34.87 +    package=g_object_new(PLOVER_TYPE_PACKAGE,NULL);
   34.88 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   34.89 +    priv->set=set;
   34.90 +    priv->pkg=pkg;
   34.91 +    return package;
   34.92 +}
   34.93 +
   34.94 +struct razor_set *plover_package_get_razor_set(PloverPackage *package)
   34.95 +{
   34.96 +    PloverPackagePrivate *priv;
   34.97 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   34.98 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
   34.99 +    return priv->set;
  34.100 +}
  34.101 +
  34.102 +struct razor_package *plover_package_get_razor_package(PloverPackage *package)
  34.103 +{
  34.104 +    PloverPackagePrivate *priv;
  34.105 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.106 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.107 +    return priv->pkg;
  34.108 +}
  34.109 +
  34.110 +const char *plover_package_get_name(PloverPackage *package)
  34.111 +{
  34.112 +    PloverPackagePrivate *priv;
  34.113 +    const char *name=NULL;
  34.114 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.115 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.116 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_NAME,&name,
  34.117 +      RAZOR_DETAIL_LAST);
  34.118 +    return name;
  34.119 +}
  34.120 +
  34.121 +const char *plover_package_get_summary(PloverPackage *package)
  34.122 +{
  34.123 +    PloverPackagePrivate *priv;
  34.124 +    const char *summary=NULL;
  34.125 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.126 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.127 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_SUMMARY,&summary,
  34.128 +      RAZOR_DETAIL_LAST);
  34.129 +    return summary;
  34.130 +}
  34.131 +
  34.132 +const char *plover_package_get_version(PloverPackage *package)
  34.133 +{
  34.134 +    PloverPackagePrivate *priv;
  34.135 +    const char *version=NULL;
  34.136 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.137 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.138 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_VERSION,&version,
  34.139 +      RAZOR_DETAIL_LAST);
  34.140 +    return version;
  34.141 +}
  34.142 +
  34.143 +const char *plover_package_get_license(PloverPackage *package)
  34.144 +{
  34.145 +    PloverPackagePrivate *priv;
  34.146 +    const char *license=NULL;
  34.147 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.148 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.149 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_LICENSE,&license,
  34.150 +      RAZOR_DETAIL_LAST);
  34.151 +    return license;
  34.152 +}
  34.153 +
  34.154 +const char *plover_package_get_arch(PloverPackage *package)
  34.155 +{
  34.156 +    PloverPackagePrivate *priv;
  34.157 +    const char *arch=NULL;
  34.158 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.159 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.160 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_ARCH,&arch,
  34.161 +      RAZOR_DETAIL_LAST);
  34.162 +    return arch;
  34.163 +}
  34.164 +
  34.165 +const char *plover_package_get_description(PloverPackage *package)
  34.166 +{
  34.167 +    PloverPackagePrivate *priv;
  34.168 +    const char *description=NULL;
  34.169 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.170 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.171 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_DESCRIPTION,
  34.172 +      &description,RAZOR_DETAIL_LAST);
  34.173 +    return description;
  34.174 +}
  34.175 +
  34.176 +const char *plover_package_get_URL(PloverPackage *package)
  34.177 +{
  34.178 +    PloverPackagePrivate *priv;
  34.179 +    const char *URL=NULL;
  34.180 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.181 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.182 +    razor_package_get_details(priv->set,priv->pkg,RAZOR_DETAIL_URL,&URL,
  34.183 +      RAZOR_DETAIL_LAST);
  34.184 +    return URL;
  34.185 +}
  34.186 +
  34.187 +/**
  34.188 + * plover_package_read_icon:
  34.189 + * @package: #PloverPackage to read icon from
  34.190 + * @error: a #GError, or %NULL
  34.191 + *
  34.192 + * Opens an icon for reading. The result is a #GInputStream that
  34.193 + * can be used to read the contents of the file.
  34.194 + *
  34.195 + * If the icon does not exist, the %G_IO_ERROR_NOT_FOUND error will be
  34.196 + * returned. Other errors are possible too.
  34.197 + *
  34.198 + * Returns: (transfer full): #GInputStream or %NULL on error.
  34.199 + *     Free the returned object with g_object_unref().
  34.200 + */
  34.201 +GInputStream *plover_package_read_icon(PloverPackage *package,GError **error)
  34.202 +{
  34.203 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.204 +    g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_NOT_SUPPORTED,
  34.205 +      "Operation not supported");
  34.206 +    return NULL;
  34.207 +}
  34.208 +
  34.209 +/**
  34.210 + * plover_package_property_iterator_create:
  34.211 + * @package: #PloverPackage to create property iterator for
  34.212 + *
  34.213 + * Creates a property iterator for package. The result is a
  34.214 + * #struct razor_property_iterator that can be used to iterate over the
  34.215 + * properties of a package.
  34.216 + *
  34.217 + * Returns: (transfer full): #struct razor_property_iterator or %NULL on error.
  34.218 + *     Free the returned iterator with razor_property_iterator_destroy().
  34.219 + */
  34.220 +struct razor_property_iterator *
  34.221 +  plover_package_property_iterator_create(PloverPackage *package)
  34.222 +{
  34.223 +    PloverPackagePrivate *priv;
  34.224 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.225 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.226 +    return razor_property_iterator_create(priv->set,priv->pkg);
  34.227 +}
  34.228 +
  34.229 +/**
  34.230 + * plover_package_file_iterator_create:
  34.231 + * @package: #PloverPackage to create file iterator for
  34.232 + * @reverse: %TRUE if the files should be iterated in reverse order
  34.233 + *
  34.234 + * Creates a file iterator for package. The result is a
  34.235 + * #struct razor_file_iterator that can be used to iterate over the files
  34.236 + * in a package.
  34.237 + *
  34.238 + * Returns: (transfer full): #struct razor_file_iterator or %NULL on error.
  34.239 + *     Free the returned iterator with razor_file_iterator_destroy().
  34.240 + */
  34.241 +struct razor_file_iterator *
  34.242 +  plover_package_file_iterator_create(PloverPackage *package,gboolean reverse)
  34.243 +{
  34.244 +    PloverPackagePrivate *priv;
  34.245 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.246 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.247 +    return razor_file_iterator_create(priv->set,priv->pkg,reverse);
  34.248 +}
  34.249 +
  34.250 +/**
  34.251 + * plover_package_get_prefixes:
  34.252 + * @package: #PloverPackage to get prefixes for
  34.253 + *
  34.254 + * Retrieve the prefixes for a relocatable package.
  34.255 + *
  34.256 + * Returns: (transfer none): NULL-terminated array of prefixes.
  34.257 + */
  34.258 +const char *const *plover_package_get_prefixes(PloverPackage *package)
  34.259 +{
  34.260 +    const char *prefix;
  34.261 +    struct razor_string_iterator *si;
  34.262 +    GPtrArray *prefixes;
  34.263 +    PloverPackagePrivate *priv;
  34.264 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  34.265 +    priv=PLOVER_PACKAGE_GET_PRIVATE(package);
  34.266 +    if (!priv->prefixes)
  34.267 +    {
  34.268 +	prefixes=g_ptr_array_new();
  34.269 +	si=razor_install_prefix_iterator_create(priv->set,priv->pkg);
  34.270 +	while (razor_string_iterator_next(si,&prefix))
  34.271 +	    g_ptr_array_add(prefixes,prefix);
  34.272 +	razor_string_iterator_destroy(si);
  34.273 +	g_ptr_array_add(prefixes,NULL);
  34.274 +	priv->prefixes=g_ptr_array_free(prefixes,FALSE);
  34.275 +    }
  34.276 +    return priv->prefixes;
  34.277 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/plover/package.h	Sat Nov 15 19:04:45 2014 +0000
    35.3 @@ -0,0 +1,56 @@
    35.4 +#ifndef __PLOVER_PACKAGE_H__
    35.5 +#define __PLOVER_PACKAGE_H__
    35.6 +
    35.7 +#include <razor.h>
    35.8 +#include <glib-object.h>
    35.9 +#include <gio/gio.h>
   35.10 +
   35.11 +G_BEGIN_DECLS
   35.12 +
   35.13 +#define PLOVER_TYPE_PACKAGE	plover_package_get_type()
   35.14 +#define PLOVER_PACKAGE(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   35.15 +				  PLOVER_TYPE_PACKAGE,PloverPackage)
   35.16 +#define PLOVER_PACKAGE_CLASS(klass)\
   35.17 +				G_TYPE_CHECK_CLASS_CAST(klass,\
   35.18 +				  PLOVER_TYPE_PACKAGE,PloverPackageClass)
   35.19 +#define PLOVER_IS_PACKAGE(obj)	G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   35.20 +				  PLOVER_TYPE_PACKAGE)
   35.21 +#define PLOVER_IS_PACKAGE_CLASS(klass)\
   35.22 +				G_TYPE_CHECK_CLASS_TYPE(obj,\
   35.23 +				  PLOVER_TYPE_PACKAGE)
   35.24 +#define PLOVER_PACKAGE_GET_CLASS(obj)\
   35.25 +				G_TYPE_INSTANCE_GET_CLASS(obj,\
   35.26 +				  PLOVER_TYPE_PACKAGE,PloverPackageClass)
   35.27 +
   35.28 +typedef struct _PloverPackage {
   35.29 +    GObject parent_instance;
   35.30 +} PloverPackage;
   35.31 +
   35.32 +typedef struct _PloverPackageClass {
   35.33 +    GObjectClass parent_class;
   35.34 +} PloverPackageClass;
   35.35 +
   35.36 +#include <plover/packageset.h>
   35.37 +
   35.38 +GType plover_package_get_type(void) G_GNUC_CONST;
   35.39 +PloverPackage *plover_package_new(struct razor_set *set,
   35.40 +  struct razor_package *pkg);
   35.41 +struct razor_set *plover_package_get_razor_set(PloverPackage *package);
   35.42 +struct razor_package *plover_package_get_razor_package(PloverPackage *package);
   35.43 +const char *plover_package_get_name(PloverPackage *package);
   35.44 +const char *plover_package_get_summary(PloverPackage *package);
   35.45 +const char *plover_package_get_version(PloverPackage *package);
   35.46 +const char *plover_package_get_license(PloverPackage *package);
   35.47 +const char *plover_package_get_arch(PloverPackage *package);
   35.48 +const char *plover_package_get_description(PloverPackage *package);
   35.49 +const char *plover_package_get_URL(PloverPackage *package);
   35.50 +GInputStream *plover_package_get_icon_stream(PloverPackage *package);
   35.51 +struct razor_property_iterator *
   35.52 +  plover_package_property_iterator_create(PloverPackage *package);
   35.53 +struct razor_file_iterator *
   35.54 +  plover_package_file_iterator_create(PloverPackage *package,gboolean reverse);
   35.55 +const char *const *plover_package_get_prefixes(PloverPackage *package);
   35.56 +
   35.57 +G_END_DECLS
   35.58 +
   35.59 +#endif /* __PLOVER_PACKAGE_H__ */
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/plover/packageset.c	Sat Nov 15 19:04:45 2014 +0000
    36.3 @@ -0,0 +1,658 @@
    36.4 +/*
    36.5 + * Copyright (C) 2010-2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    36.6 + *
    36.7 + * This program is free software; you can redistribute it and/or modify
    36.8 + * it under the terms of the GNU General Public License as published by
    36.9 + * the Free Software Foundation; either version 2 of the License, or
   36.10 + * (at your option) any later version.
   36.11 + *
   36.12 + * This program is distributed in the hope that it will be useful,
   36.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.15 + * GNU General Public License for more details.
   36.16 + *
   36.17 + * You should have received a copy of the GNU General Public License along
   36.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   36.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   36.20 + */
   36.21 +
   36.22 +#include "config.h"
   36.23 +#include <stdlib.h>
   36.24 +#include <string.h>
   36.25 +#include <fcntl.h>
   36.26 +#include <errno.h>
   36.27 +#include <unistd.h>
   36.28 +#include <glib-object.h>
   36.29 +#include <razor.h>
   36.30 +#include "plover/plover.h"
   36.31 +#include "plover/package.h"
   36.32 +#include "plover/packageset.h"
   36.33 +
   36.34 +G_DEFINE_TYPE(PloverPackageSet,plover_package_set,G_TYPE_OBJECT);
   36.35 +
   36.36 +typedef struct _PloverPackageSetPrivate {
   36.37 +    gchar *install_root;
   36.38 +    struct razor_root *root;
   36.39 +    struct razor_set *set;
   36.40 +    GSList *packages;
   36.41 +    int no_details;
   36.42 +    gchar *guessed_prefix;
   36.43 +} PloverPackageSetPrivate;
   36.44 +
   36.45 +#define PLOVER_PACKAGE_SET_GET_PRIVATE(obj)\
   36.46 +				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
   36.47 +				  PLOVER_TYPE_PACKAGE_SET,\
   36.48 +				  PloverPackageSetPrivate)
   36.49 +
   36.50 +enum {
   36.51 +    CHANGED=0,
   36.52 +    N_SIGNALS
   36.53 +};
   36.54 +
   36.55 +static guint signals[N_SIGNALS];
   36.56 +
   36.57 +static void plover_package_set_finalize(GObject *obj)
   36.58 +{
   36.59 +    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
   36.60 +    g_free(priv->guessed_prefix);
   36.61 +    G_OBJECT_CLASS(plover_package_set_parent_class)->finalize(obj);
   36.62 +}
   36.63 +
   36.64 +static void plover_package_set_dispose(GObject *obj)
   36.65 +{
   36.66 +    PloverPackageSetPrivate *priv=PLOVER_PACKAGE_SET_GET_PRIVATE(obj);
   36.67 +    if (priv->set)
   36.68 +    {
   36.69 +	razor_set_unref(priv->set);
   36.70 +	priv->set=NULL;
   36.71 +    }
   36.72 +    if (priv->root)
   36.73 +    {
   36.74 +	g_free(priv->install_root);
   36.75 +	priv->install_root=NULL;
   36.76 +	razor_root_close(priv->root);
   36.77 +	priv->root=NULL;
   36.78 +    }
   36.79 +    G_OBJECT_CLASS(plover_package_set_parent_class)->dispose(obj);
   36.80 +}
   36.81 +
   36.82 +static void plover_package_set_class_init(PloverPackageSetClass *klass)
   36.83 +{
   36.84 +    GObjectClass *oclass=G_OBJECT_CLASS(klass);
   36.85 +    oclass->finalize=plover_package_set_finalize;
   36.86 +    oclass->dispose=plover_package_set_dispose;
   36.87 +    g_type_class_add_private(klass,sizeof(PloverPackageSetPrivate));
   36.88 +    signals[CHANGED]=g_signal_newv("changed",
   36.89 +      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
   36.90 +      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
   36.91 +}
   36.92 +
   36.93 +static void plover_package_set_init(PloverPackageSet *set)
   36.94 +{
   36.95 +    PloverPackageSetPrivate *priv;
   36.96 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
   36.97 +    priv->no_details=-1;
   36.98 +}
   36.99 +
  36.100 +PloverPackageSet *plover_package_set_new(void)
  36.101 +{
  36.102 +    return g_object_new(PLOVER_TYPE_PACKAGE_SET,NULL);
  36.103 +}
  36.104 +
  36.105 +void plover_package_set_close(PloverPackageSet *set)
  36.106 +{
  36.107 +    PloverPackageSetPrivate *priv;
  36.108 +    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
  36.109 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.110 +    if (priv->root)
  36.111 +    {
  36.112 +	razor_root_close(priv->root);
  36.113 +	priv->root=NULL;
  36.114 +    }
  36.115 +}
  36.116 +
  36.117 +gboolean plover_package_set_open(PloverPackageSet *set,const char *install_root,
  36.118 +  gboolean exclusive,GError **err)
  36.119 +{
  36.120 +    struct razor_root *root=NULL;
  36.121 +    struct razor_set *system=NULL;
  36.122 +    PloverPackageSetPrivate *priv;
  36.123 +    struct razor_error *error=NULL;
  36.124 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  36.125 +    if (exclusive)
  36.126 +    {
  36.127 +	root=razor_root_open(install_root,NULL);
  36.128 +	if (!root)
  36.129 +	{
  36.130 +	    if (razor_root_create(install_root,&error))
  36.131 +	    {
  36.132 +		if (razor_error_get_domain(error)==RAZOR_GENERAL_ERROR &&
  36.133 +		  razor_error_get_code(error)==
  36.134 +		  RAZOR_GENERAL_ERROR_DATABASE_EXISTS)
  36.135 +		{
  36.136 +		    razor_error_free(error);
  36.137 +		    error=NULL;
  36.138 +		    root=razor_root_open(install_root,&error);
  36.139 +		}                             
  36.140 +	    }
  36.141 +	    else
  36.142 +		root=razor_root_open(install_root,&error);
  36.143 +	    if (!root)                        
  36.144 +	    {
  36.145 +		plover_propagate_razor_error(err,error);
  36.146 +		return FALSE;
  36.147 +	    }
  36.148 +	}
  36.149 +	system=razor_root_get_system_set(root);
  36.150 +	if (system)
  36.151 +	    razor_set_ref(system);
  36.152 +    }
  36.153 +    else
  36.154 +	system=razor_root_open_read_only(install_root,&error);
  36.155 +    if (error)
  36.156 +    {
  36.157 +	g_set_error_literal(err,PLOVER_RAZOR_ERROR,RAZOR_GENERAL_ERROR_FAILED,
  36.158 +	  razor_error_get_msg(error));
  36.159 +	razor_error_free(error);
  36.160 +	return FALSE;
  36.161 +    }
  36.162 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.163 +    if (priv->set)
  36.164 +    {
  36.165 +	razor_set_unref(priv->set);
  36.166 +	priv->set=NULL;
  36.167 +    }
  36.168 +    if (priv->root)
  36.169 +    {
  36.170 +	razor_root_close(priv->root);
  36.171 +	priv->root=NULL;
  36.172 +    }
  36.173 +    g_free(priv->install_root);
  36.174 +    priv->install_root=g_strdup(install_root);
  36.175 +    priv->root=root;
  36.176 +    priv->set=system;
  36.177 +    return TRUE;
  36.178 +}
  36.179 +
  36.180 +const char *plover_package_set_get_install_root(PloverPackageSet *set)
  36.181 +{
  36.182 +    PloverPackageSetPrivate *priv;
  36.183 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.184 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.185 +    return priv->install_root;
  36.186 +}
  36.187 +
  36.188 +gboolean plover_package_set_get_exclusive(PloverPackageSet *set)
  36.189 +{
  36.190 +    PloverPackageSetPrivate *priv;
  36.191 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  36.192 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.193 +    return !!priv->root;
  36.194 +}
  36.195 +
  36.196 +gboolean plover_package_set_update(PloverPackageSet *set,struct razor_set *next,
  36.197 +  struct razor_atomic *atomic)
  36.198 +{
  36.199 +    gboolean retval;
  36.200 +    PloverPackageSetPrivate *priv;
  36.201 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  36.202 +    g_return_val_if_fail(plover_package_set_get_exclusive(set) != FALSE,FALSE);
  36.203 +    g_return_val_if_fail(next != NULL,FALSE);
  36.204 +    g_return_val_if_fail(atomic != NULL,FALSE);
  36.205 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.206 +    retval=!razor_root_update(priv->root,next,atomic);
  36.207 +    if (retval)
  36.208 +    {
  36.209 +	razor_set_unref(priv->set);
  36.210 +	priv->set=razor_root_get_system_set(priv->root);
  36.211 +	if (priv->set)
  36.212 +	    razor_set_ref(priv->set);
  36.213 +    }
  36.214 +    return retval;
  36.215 +}
  36.216 +
  36.217 +PloverPackageSet *plover_package_set_new_from_installed(const char *root,
  36.218 +  GError **err)
  36.219 +{
  36.220 +    PloverPackageSet *set;
  36.221 +    set=plover_package_set_new();
  36.222 +    if (!plover_package_set_open(set,root,FALSE,err))
  36.223 +    {
  36.224 +	g_object_unref(set);
  36.225 +	return NULL;
  36.226 +    }
  36.227 +    return set;
  36.228 +}
  36.229 +
  36.230 +PloverPackageSet *plover_package_set_new_from_razor(struct razor_set *razor)
  36.231 +{
  36.232 +    PloverPackageSet *set;
  36.233 +    PloverPackageSetPrivate *priv;
  36.234 +    g_return_val_if_fail(razor != NULL,NULL);
  36.235 +    set=plover_package_set_new();
  36.236 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.237 +    priv->set=razor;
  36.238 +    razor_set_ref(priv->set);
  36.239 +    return set;
  36.240 +}
  36.241 +
  36.242 +static gboolean
  36.243 +  plover_package_set_import_package(PloverRepository *repository,
  36.244 +  struct razor_relocations *relocations,struct razor_importer *importer,
  36.245 +  PloverPackage *package,GError **error)
  36.246 +{
  36.247 +    struct razor_property_iterator *prop_iter;
  36.248 +    struct razor_file_iterator *file_iter;
  36.249 +    struct razor_rpm *rpm;
  36.250 +    struct razor_property *prop;
  36.251 +    const char *name,*version,*arch,*summary,*desc,*url,*license;
  36.252 +    uint32_t flags;
  36.253 +    rpm=plover_repository_open_rpm(repository,package,error);
  36.254 +    if (!rpm)
  36.255 +	return FALSE;
  36.256 +    razor_relocations_set_rpm(relocations,rpm);
  36.257 +    razor_rpm_close(rpm);
  36.258 +    name=plover_package_get_name(package);
  36.259 +    version=plover_package_get_version(package);
  36.260 +    arch=plover_package_get_arch(package);
  36.261 +    razor_importer_begin_package(importer,name,version,arch);
  36.262 +    summary=plover_package_get_summary(package);
  36.263 +    desc=plover_package_get_description(package);
  36.264 +    url=plover_package_get_URL(package);
  36.265 +    license=plover_package_get_license(package);
  36.266 +    razor_importer_add_details(importer,summary,desc,url,license);
  36.267 +    prop_iter=plover_package_property_iterator_create(package);
  36.268 +    while (razor_property_iterator_next(prop_iter,&prop,&name,&flags,&version))
  36.269 +	razor_importer_add_property(importer,name,flags,version);
  36.270 +    razor_property_iterator_destroy(prop_iter);
  36.271 +    file_iter=plover_package_file_iterator_create(package,FALSE);
  36.272 +    while (razor_file_iterator_next(file_iter,&name))
  36.273 +    {
  36.274 +	name=razor_relocations_apply(relocations,name);
  36.275 +	razor_importer_add_file(importer,name);
  36.276 +    }
  36.277 +    razor_file_iterator_destroy(file_iter);
  36.278 +    razor_importer_finish_package(importer);
  36.279 +    return TRUE;
  36.280 +}
  36.281 +
  36.282 +PloverPackageSet *
  36.283 +  plover_package_set_new_from_repository(PloverRepository *repository,
  36.284 +  struct razor_relocations *relocations,GError **error)
  36.285 +{
  36.286 +    struct razor_importer *importer;
  36.287 +    uint32_t header_version;
  36.288 +    GSList *packages,*lnk;
  36.289 +    PloverPackageSet *unrelocated,*set;
  36.290 +    PloverPackageSetPrivate *priv;
  36.291 +    PloverPackage *package;
  36.292 +    g_return_val_if_fail(PLOVER_IS_REPOSITORY(repository),NULL);
  36.293 +    unrelocated=plover_repository_get_package_set(repository);
  36.294 +    set=plover_package_set_new();
  36.295 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.296 +    if (relocations)
  36.297 +    {
  36.298 +	importer=razor_importer_create();
  36.299 +	packages=plover_package_set_get_packages(unrelocated);
  36.300 +	for(lnk=packages;lnk;lnk=lnk->next)
  36.301 +	{
  36.302 +	    package=lnk->data;
  36.303 +	    if (!plover_package_set_import_package(repository,relocations,
  36.304 +	      importer,package,error))
  36.305 +	    {
  36.306 +		razor_importer_destroy(importer);
  36.307 +		g_object_unref(set);
  36.308 +		return NULL;
  36.309 +	    }
  36.310 +	}
  36.311 +	priv->set=razor_importer_finish(importer);
  36.312 +	if (!priv->set)
  36.313 +	{
  36.314 +	    g_object_unref(set);
  36.315 +	    return NULL;
  36.316 +	}
  36.317 +	header_version=plover_package_set_get_header_version(unrelocated);
  36.318 +	if (header_version)
  36.319 +	    plover_package_set_set_header_version(set,header_version);
  36.320 +    }
  36.321 +    else
  36.322 +    {
  36.323 +	priv->set=plover_package_set_get_razor(unrelocated);
  36.324 +	razor_set_ref(priv->set);
  36.325 +    }
  36.326 +    return set;
  36.327 +}
  36.328 +
  36.329 +PloverPackageSet *plover_package_set_new_from_yum(const char *base,
  36.330 +  struct razor_relocations *relocations,GError **error)
  36.331 +{
  36.332 +    PloverPackageSet *set;
  36.333 +    PloverRepository *repository;
  36.334 +    repository=plover_repository_new_from_yum(base,error);
  36.335 +    if (!repository)
  36.336 +	return NULL;
  36.337 +    set=plover_package_set_new_from_repository(repository,relocations,error);
  36.338 +    g_object_unref(repository);
  36.339 +    return set;
  36.340 +}
  36.341 +
  36.342 +PloverPackageSet *plover_package_set_new_from_rpms(const char **filenames,
  36.343 +  GError **error)
  36.344 +{
  36.345 +    int i;
  36.346 +    PloverPackageSet *set;
  36.347 +    PloverPackageSetPrivate *priv;
  36.348 +    struct razor_importer *importer;
  36.349 +    struct razor_rpm *rpm;
  36.350 +    struct razor_error *tmp_error=NULL;
  36.351 +    importer=razor_importer_create();
  36.352 +    for(i=0;filenames[i];i++)
  36.353 +    {
  36.354 +	rpm=razor_rpm_open(filenames[i],&tmp_error);
  36.355 +	if (!rpm)
  36.356 +	{
  36.357 +	    razor_importer_destroy(importer);
  36.358 +	    plover_propagate_razor_error(error,tmp_error);
  36.359 +	    return NULL;
  36.360 +	}
  36.361 +	if (razor_importer_add_rpm(importer,rpm))
  36.362 +	{
  36.363 +	    g_set_error(error,PLOVER_RAZOR_ERROR,RAZOR_GENERAL_ERROR_FAILED,
  36.364 +	      "%s: failed to import",filenames[i]);
  36.365 +	    razor_importer_destroy(importer);
  36.366 +	    return NULL;
  36.367 +	}
  36.368 +	razor_rpm_close(rpm);
  36.369 +    }
  36.370 +    set=plover_package_set_new();
  36.371 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.372 +    priv->set=razor_importer_finish(importer);
  36.373 +    return set;
  36.374 +}
  36.375 +
  36.376 +uint32_t plover_package_set_get_header_version(PloverPackageSet *set)
  36.377 +{
  36.378 +    PloverPackageSetPrivate *priv;
  36.379 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),0);
  36.380 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.381 +    if (priv->set)
  36.382 +	return razor_set_get_header_version(priv->set);
  36.383 +    else
  36.384 +	return 0;
  36.385 +}
  36.386 +
  36.387 +gboolean plover_package_set_set_header_version(PloverPackageSet *set,
  36.388 +  uint32_t header_version)
  36.389 +{
  36.390 +    PloverPackageSetPrivate *priv;
  36.391 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  36.392 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.393 +    if (priv->set)
  36.394 +	return !razor_set_set_header_version(priv->set,header_version);
  36.395 +    else
  36.396 +	return FALSE;
  36.397 +}
  36.398 +
  36.399 +struct razor_set *plover_package_set_get_razor(PloverPackageSet *set)
  36.400 +{
  36.401 +    PloverPackageSetPrivate *priv;
  36.402 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.403 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.404 +    return priv->set;
  36.405 +}
  36.406 +
  36.407 +GSList *plover_package_set_get_packages(PloverPackageSet *set)
  36.408 +{
  36.409 +    struct razor_package_iterator *iter;
  36.410 +    struct razor_package *pkg;
  36.411 +    PloverPackageSetPrivate *priv;
  36.412 +    PloverPackage *package;
  36.413 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.414 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.415 +    if (priv->set && !priv->packages)
  36.416 +    {
  36.417 +	iter=razor_package_iterator_create(priv->set);
  36.418 +	while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_LAST))
  36.419 +	{
  36.420 +	    package=plover_package_new(priv->set,pkg);
  36.421 +	    priv->packages=g_slist_prepend(priv->packages,package);
  36.422 +	}
  36.423 +	razor_package_iterator_destroy(iter);
  36.424 +	priv->packages=g_slist_reverse(priv->packages);
  36.425 +    }
  36.426 +    return priv->packages;
  36.427 +}
  36.428 +
  36.429 +PloverPackage *plover_package_set_lookup(PloverPackageSet *set,
  36.430 +  struct razor_package *razor_package)
  36.431 +{
  36.432 +    GSList *packages,*lnk;
  36.433 +    PloverPackage *package;
  36.434 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.435 +    packages=plover_package_set_get_packages(set);
  36.436 +    for(lnk=packages;lnk;lnk=lnk->next)
  36.437 +    {
  36.438 +	package=lnk->data;
  36.439 +	if (plover_package_get_razor_package(package)==razor_package)
  36.440 +	    return package;
  36.441 +    }
  36.442 +    return NULL;
  36.443 +}
  36.444 +
  36.445 +PloverPackage *plover_package_set_find_custom(PloverPackageSet *set,
  36.446 +  gconstpointer data,GCompareFunc func)
  36.447 +{
  36.448 +    GSList *packages,*lnk;
  36.449 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.450 +    packages=plover_package_set_get_packages(set);
  36.451 +    lnk=g_slist_find_custom(packages,data,func);
  36.452 +    return lnk?lnk->data:NULL;
  36.453 +}
  36.454 +
  36.455 +static gint plover_package_set_compare(gconstpointer a,gconstpointer b)
  36.456 +{
  36.457 +    PloverPackage *pa=(void *)a,*pb=(void *)b;
  36.458 +    const char *sa,*sb;
  36.459 +    sa=plover_package_get_name(pa);
  36.460 +    sb=plover_package_get_name(pb);
  36.461 +    if (g_strcmp0(sa,sb))
  36.462 +	return 1;
  36.463 +    sa=plover_package_get_arch(pa);
  36.464 +    sb=plover_package_get_arch(pb);
  36.465 +    if (g_strcmp0(sa,sb))
  36.466 +	return 1;
  36.467 +    sa=plover_package_get_version(pa);
  36.468 +    sb=plover_package_get_version(pb);
  36.469 +    return !!g_strcmp0(sa,sb);
  36.470 +}
  36.471 +
  36.472 +PloverPackage *plover_package_set_find_matching(PloverPackageSet *set,
  36.473 +  PloverPackage *template)
  36.474 +{
  36.475 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.476 +    return plover_package_set_find_custom(set,template,
  36.477 +      plover_package_set_compare);
  36.478 +}
  36.479 +
  36.480 +/*
  36.481 + * Some versions of razor have a bug which causes all detail strings
  36.482 + * to be discarded. If such a version of razor is used to install or
  36.483 + * update a package, then all the detail strings for the installed
  36.484 + * set will be lost. This function tests for this condition and can
  36.485 + * be used to present something more useful than blank details.
  36.486 + */
  36.487 +
  36.488 +gboolean plover_package_set_get_no_details(PloverPackageSet *set)
  36.489 +{
  36.490 +    PloverPackageSetPrivate *priv;
  36.491 +    PloverPackage *package;
  36.492 +    GSList *packages,*link;
  36.493 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),FALSE);
  36.494 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.495 +    if (priv->no_details<0)
  36.496 +    {
  36.497 +	packages=plover_package_set_get_packages(set);
  36.498 +	if (packages)
  36.499 +	{
  36.500 +	    priv->no_details=0;
  36.501 +	    for(link=packages;link;link=link->next)
  36.502 +	    {
  36.503 +		package=link->data;
  36.504 +		priv->no_details+=2;
  36.505 +		if (*plover_package_get_summary(package))
  36.506 +		    priv->no_details--;
  36.507 +		if (*plover_package_get_license(package))
  36.508 +		    priv->no_details--;
  36.509 +		if (*plover_package_get_description(package))
  36.510 +		    priv->no_details--;
  36.511 +		if (*plover_package_get_URL(package))
  36.512 +		    priv->no_details--;
  36.513 +	    }
  36.514 +	    if (priv->no_details<0)	/* More than 50% of strings present */
  36.515 +		priv->no_details=0;
  36.516 +	}
  36.517 +    }
  36.518 +    return priv->no_details>0;
  36.519 +}
  36.520 +
  36.521 +struct plover_package_set_prefix {
  36.522 +    gchar *path;
  36.523 +    guint count;
  36.524 +};
  36.525 +
  36.526 +static GArray *plover_package_set_popchart_new(void)
  36.527 +{
  36.528 +    GArray *prefixes;
  36.529 +    prefixes=g_array_new(FALSE,FALSE,sizeof(struct plover_package_set_prefix));
  36.530 +    return prefixes;
  36.531 +}
  36.532 +
  36.533 +static void plover_package_set_popchart_free(GArray *popchart)
  36.534 +{
  36.535 +    int i;
  36.536 +    struct plover_package_set_prefix *prefix;
  36.537 +    for(i=0;i<popchart->len;i++)
  36.538 +    {
  36.539 +	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
  36.540 +	g_free(prefix->path);
  36.541 +    }
  36.542 +    g_array_free(popchart,TRUE);
  36.543 +}
  36.544 +
  36.545 +static void plover_package_set_popchart_add(GArray *popchart,const char *path)
  36.546 +{
  36.547 +    int i;
  36.548 +    struct plover_package_set_prefix *prefix;
  36.549 +    for(i=popchart->len-1;i>=0;i--)
  36.550 +    {
  36.551 +	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
  36.552 +	if (!strcmp(prefix->path,path))
  36.553 +	{
  36.554 +	    prefix->count++;
  36.555 +	    return;
  36.556 +	}
  36.557 +    }
  36.558 +    g_array_set_size(popchart,popchart->len+1);
  36.559 +    prefix=&g_array_index(popchart,struct plover_package_set_prefix,
  36.560 +      popchart->len-1);
  36.561 +    prefix->path=g_strdup(path);
  36.562 +    prefix->count=1;
  36.563 +}
  36.564 +
  36.565 +static const char *plover_package_set_popchart_get_popular(GArray *popchart)
  36.566 +{
  36.567 +    int i;
  36.568 +    struct plover_package_set_prefix *prefix,*popular;
  36.569 +    if (!popchart->len)
  36.570 +	return NULL;
  36.571 +    popular=&g_array_index(popchart,struct plover_package_set_prefix,0);
  36.572 +    for(i=1;i<popchart->len;i++)
  36.573 +    {
  36.574 +	prefix=&g_array_index(popchart,struct plover_package_set_prefix,i);
  36.575 +	if (prefix->count>popular->count)
  36.576 +	    popular=prefix;
  36.577 +    }
  36.578 +    return popular->path;
  36.579 +}
  36.580 +
  36.581 +static void plover_package_set_popchart_add_prefixes(PloverPackageSet *set,
  36.582 +  GArray *popchart)
  36.583 +{
  36.584 +    int i;
  36.585 +    PloverPackage *package;
  36.586 +    GSList *packages,*lnk;
  36.587 +    const char *const *prefixes;
  36.588 +    packages=plover_package_set_get_packages(set);
  36.589 +    for(lnk=packages;lnk;lnk=lnk->next)
  36.590 +    {
  36.591 +	package=lnk->data;
  36.592 +	prefixes=plover_package_get_prefixes(package);
  36.593 +	for(i=0;prefixes[i];i++)
  36.594 +	    plover_package_set_popchart_add(popchart,prefixes[i]);
  36.595 +    }
  36.596 +}
  36.597 +
  36.598 +static void plover_package_set_popchart_add_from_files(PloverPackageSet *set,
  36.599 +  GArray *popchart)
  36.600 +{
  36.601 +    int len;
  36.602 +    const char *name,*s;
  36.603 +    gchar *default_prefix,*path;
  36.604 +    struct razor_file_iterator *fi;
  36.605 +    GSList *packages,*lnk;
  36.606 +    PloverPackage *package;
  36.607 +    default_prefix=plover_default_prefix_for_vendor("");
  36.608 +    if (!default_prefix)
  36.609 +	return;
  36.610 +    len=strlen(default_prefix);
  36.611 +    packages=plover_package_set_get_packages(set);
  36.612 +    for(lnk=packages;lnk;lnk=lnk->next)
  36.613 +    {
  36.614 +	package=lnk->data;
  36.615 +	fi=plover_package_file_iterator_create(package,FALSE);
  36.616 +	while (razor_file_iterator_next(fi,&name))
  36.617 +	{
  36.618 +	    if (g_str_has_prefix(name,default_prefix))
  36.619 +	    {
  36.620 +		for(s=name+len;*s;s++)
  36.621 +		    if (G_IS_DIR_SEPARATOR(*s))
  36.622 +			break;
  36.623 +		path=g_strndup(name,s-name);
  36.624 +		plover_package_set_popchart_add(popchart,path);
  36.625 +		g_free(path);
  36.626 +	    }
  36.627 +	}
  36.628 +	razor_file_iterator_destroy(fi);
  36.629 +    }
  36.630 +    g_free(default_prefix);
  36.631 +}
  36.632 +
  36.633 +const char *plover_package_set_guess_prefix(PloverPackageSet *set,
  36.634 +  GError **error)
  36.635 +{
  36.636 +    GArray *popchart;
  36.637 +    const char *prefix;
  36.638 +    PloverPackageSetPrivate *priv;
  36.639 +    g_return_val_if_fail(PLOVER_IS_PACKAGE_SET(set),NULL);
  36.640 +    priv=PLOVER_PACKAGE_SET_GET_PRIVATE(set);
  36.641 +    if (!priv->guessed_prefix)
  36.642 +    {
  36.643 +	popchart=plover_package_set_popchart_new();
  36.644 +	plover_package_set_popchart_add_prefixes(set,popchart);
  36.645 +	prefix=plover_package_set_popchart_get_popular(popchart);
  36.646 +	if (prefix)
  36.647 +	    priv->guessed_prefix=g_strdup(prefix);
  36.648 +	else
  36.649 +	{
  36.650 +	    plover_package_set_popchart_add_from_files(set,popchart);
  36.651 +	    prefix=plover_package_set_popchart_get_popular(popchart);
  36.652 +	    if (prefix)
  36.653 +		priv->guessed_prefix=g_strdup(prefix);
  36.654 +	}
  36.655 +	plover_package_set_popchart_free(popchart);
  36.656 +    }
  36.657 +    if (!priv->guessed_prefix)
  36.658 +	priv->guessed_prefix=
  36.659 +	  plover_default_prefix_for_vendor("Acme Corporation");
  36.660 +    return priv->guessed_prefix;
  36.661 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/plover/packageset.h	Sat Nov 15 19:04:45 2014 +0000
    37.3 @@ -0,0 +1,73 @@
    37.4 +#ifndef __PLOVER_PACKAGE_SET_H__
    37.5 +#define __PLOVER_PACKAGE_SET_H__
    37.6 +
    37.7 +#include <razor.h>
    37.8 +#include <glib-object.h>
    37.9 +
   37.10 +G_BEGIN_DECLS
   37.11 +
   37.12 +#define PLOVER_TYPE_PACKAGE_SET	plover_package_set_get_type()
   37.13 +#define PLOVER_PACKAGE_SET(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   37.14 +				  PLOVER_TYPE_PACKAGE_SET,PloverPackageSet)
   37.15 +#define PLOVER_PACKAGE_SET_CLASS(klass)\
   37.16 +				G_TYPE_CHECK_CLASS_CAST(klass,\
   37.17 +				  PLOVER_TYPE_PACKAGE_SET,\
   37.18 +				  PloverPackageSetClass)
   37.19 +#define PLOVER_IS_PACKAGE_SET(obj)\
   37.20 +				G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   37.21 +				  PLOVER_TYPE_PACKAGE_SET)
   37.22 +#define PLOVER_IS_PACKAGE_SET_CLASS(klass)\
   37.23 +				G_TYPE_CHECK_CLASS_TYPE(obj,\
   37.24 +				  PLOVER_TYPE_PACKAGE_SET)
   37.25 +#define PLOVER_PACKAGE_SET_GET_CLASS(obj)\
   37.26 +				G_TYPE_INSTANCE_GET_CLASS(obj,\
   37.27 +				  PLOVER_TYPE_PACKAGE_SET,\
   37.28 +				  PloverPackageSetClass)
   37.29 +
   37.30 +typedef struct _PloverPackageSet {
   37.31 +    GObject parent_instance;
   37.32 +} PloverPackageSet;
   37.33 +
   37.34 +typedef struct _PloverPackageSetClass {
   37.35 +    GObjectClass parent_class;
   37.36 +} PloverPackageSetClass;
   37.37 +
   37.38 +#include <plover/repository.h>
   37.39 +
   37.40 +GType plover_package_set_get_type(void) G_GNUC_CONST;
   37.41 +PloverPackageSet *plover_package_set_new(void);
   37.42 +void plover_package_set_close(PloverPackageSet *set);
   37.43 +gboolean plover_package_set_open(PloverPackageSet *set,const char *install_root,
   37.44 +  gboolean exclusive,GError **err);
   37.45 +gboolean plover_package_set_update(PloverPackageSet *set,struct razor_set *next,
   37.46 +  struct razor_atomic *atomic);
   37.47 +const char *plover_package_set_get_install_root(PloverPackageSet *set);
   37.48 +gboolean plover_package_set_get_exclusive(PloverPackageSet *set);
   37.49 +PloverPackageSet *plover_package_set_new_from_installed(const char *root,
   37.50 +  GError **err);
   37.51 +PloverPackageSet *plover_package_set_new_from_razor(struct razor_set *razor);
   37.52 +PloverPackageSet *
   37.53 +  plover_package_set_new_from_repository(PloverRepository *repository,
   37.54 +  struct razor_relocations *relocations,GError **err);
   37.55 +PloverPackageSet *plover_package_set_new_from_yum(const char *base,
   37.56 +  struct razor_relocations *relocations,GError **err);
   37.57 +PloverPackageSet *plover_package_set_new_from_rpms(const char **filenames,
   37.58 +  GError **error);
   37.59 +uint32_t plover_package_set_get_header_version(PloverPackageSet *set);
   37.60 +gboolean plover_package_set_set_header_version(PloverPackageSet *set,
   37.61 +  uint32_t header_version);
   37.62 +struct razor_set *plover_package_set_get_razor(PloverPackageSet *set);
   37.63 +GSList *plover_package_set_get_packages(PloverPackageSet *set);
   37.64 +PloverPackage *plover_package_set_lookup(PloverPackageSet *set,
   37.65 +  struct razor_package *razor_package);
   37.66 +PloverPackage *plover_package_set_find_custom(PloverPackageSet *set,
   37.67 +  gconstpointer data,GCompareFunc func);
   37.68 +PloverPackage *plover_package_set_find_matching(PloverPackageSet *set,
   37.69 +  PloverPackage *template);
   37.70 +gboolean plover_package_set_get_no_details(PloverPackageSet *set);
   37.71 +const char *plover_package_set_guess_prefix(PloverPackageSet *set,
   37.72 +  GError **error);
   37.73 +
   37.74 +G_END_DECLS
   37.75 +
   37.76 +#endif /* __PLOVER_PACKAGE_SET_H__ */
    38.1 --- a/plover/plover.h	Fri Mar 23 20:29:50 2012 +0000
    38.2 +++ b/plover/plover.h	Sat Nov 15 19:04:45 2014 +0000
    38.3 @@ -2,6 +2,26 @@
    38.4  #define __PLOVER_H__
    38.5  
    38.6  #include <razor.h>
    38.7 +#include <glib.h>
    38.8 +#include <gio/gio.h>
    38.9 +#include <plover/packageset.h>
   38.10 +#include <plover/repository.h>
   38.11 +
   38.12 +#define PLOVER_GENERAL_ERROR		RAZOR_ERROR_DOMAIN('P','l','v',0)
   38.13 +#define PLOVER_SCRIPTLET_ERROR		RAZOR_ERROR_DOMAIN('P','l','v',1)
   38.14 +#define PLOVER_RAZOR_ERROR		plover_razor_error_quark()
   38.15 +#define PLOVER_POSIX_ERROR		plover_posix_error_quark()
   38.16 +#define PLOVER_MSWIN_ERROR		plover_mswin_error_quark()
   38.17 +#define PLOVER_ZLIB_ERROR		plover_zlib_error_quark()
   38.18 +
   38.19 +enum plover_general_error
   38.20 +{
   38.21 +    PLOVER_GENERAL_ERROR_FAILED,
   38.22 +    PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,
   38.23 +    PLOVER_GENERAL_ERROR_NO_WORK,
   38.24 +    PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET,
   38.25 +    PLOVER_GENERAL_ERROR_CANCELLED,
   38.26 +};
   38.27  
   38.28  enum comps_requirement_type
   38.29  {
   38.30 @@ -33,25 +53,36 @@
   38.31      struct comps_group *groups;
   38.32  };
   38.33  
   38.34 -char *plover_strconcat(const char *string,...);
   38.35 -char *plover_default_prefix_for_vendor(const char *vendor);
   38.36 +struct plover_vector
   38.37 +{
   38.38 +    int len,alloc;
   38.39 +    char **strings;
   38.40 +};
   38.41 +
   38.42 +gchar *plover_default_prefix_for_vendor(const char *vendor);
   38.43 +gchar *plover_pre_install_prefix(void);
   38.44  char *plover_get_program_directory(const char *argv0);
   38.45 +GQuark plover_razor_error_quark(void);
   38.46 +GQuark plover_posix_error_quark(void);
   38.47 +GQuark plover_mswin_error_quark(void);
   38.48 +GQuark plover_zlib_error_quark(void);
   38.49 +void plover_propagate_razor_error_dup(GError **dest,struct razor_error *src);
   38.50 +void plover_propagate_razor_error(GError **dest,struct razor_error *src);
   38.51 +void plover_propagate_g_error(struct razor_error **dest,GError *src);
   38.52  
   38.53 -struct razor_set *plover_razor_set_create_from_yum(const char *base);
   38.54 +struct razor_set *plover_razor_set_create_from_yum(const char *base,
   38.55 +  GError **error);
   38.56  
   38.57 -struct razor_set *plover_relocate_packages(struct razor_set *set,
   38.58 -  const char *base,struct razor_relocations *relocations,
   38.59 -  struct razor_error **error);
   38.60  int plover_run_transaction(struct razor_transaction *trans,
   38.61 -  struct razor_install_iterator *ii,const char *base,const char *install_root,
   38.62 -  struct razor_set *system,struct razor_set *next,struct razor_atomic *atomic,
   38.63 -  struct razor_relocations *relocations,enum razor_stage_type stage);
   38.64 -int plover_commit_transaction(struct razor_transaction *trans,const char *base,
   38.65 -  const char *install_root,struct razor_root *root,
   38.66 -  struct razor_relocations *relocations);
   38.67 -int plover_install(const char *base,const char *prefix,char **pkgs);
   38.68 -int plover_update(const char *base,const char *prefix,char **pkgs);
   38.69 -int plover_remove(char **pkgs);
   38.70 +  struct razor_install_iterator *ii,const char *install_root,
   38.71 +  struct razor_set *system,PloverPackageSet *next,PloverRepository *upstream,
   38.72 +  struct razor_atomic *atomic,struct razor_relocations *relocations,
   38.73 +  enum razor_stage_type stage,GCancellable *cancellable);
   38.74 +gboolean plover_install(const char *base,const char *prefix,char **pkgs,
   38.75 +  GError **error);
   38.76 +gboolean plover_update(const char *base,const char *prefix,char **pkgs,
   38.77 +  GError **error);
   38.78 +gboolean plover_remove(char **pkgs,GError **error);
   38.79  int plover_installed_files_match_prefix(const char *prefix);
   38.80  
   38.81  struct comps *plover_comps_new(void);
   38.82 @@ -60,4 +91,15 @@
   38.83  struct comps_group *plover_comps_lookup_group(struct comps *comps,
   38.84    const char *id);
   38.85  
   38.86 +int plover_log_open(const char *path);
   38.87 +
   38.88 +struct plover_vector *plover_vector_new(void);
   38.89 +struct plover_vector *plover_vector_dup(struct plover_vector *old);
   38.90 +void plover_vector_append(struct plover_vector *vector,const char *str);
   38.91 +int plover_vector_contains(struct plover_vector *vector,const char *str);
   38.92 +int plover_vector_remove(struct plover_vector *vector,const char *str);
   38.93 +void plover_vector_sort(struct plover_vector *vector);
   38.94 +char *plover_vector_format_for_display(struct plover_vector *vector);
   38.95 +void plover_vector_free(struct plover_vector *vector);
   38.96 +
   38.97  #endif /* __PLOVER_H__ */
    39.1 --- a/plover/plover.pc.in	Fri Mar 23 20:29:50 2012 +0000
    39.2 +++ b/plover/plover.pc.in	Sat Nov 15 19:04:45 2014 +0000
    39.3 @@ -6,6 +6,6 @@
    39.4  Name: plover
    39.5  Description: Plover packaging system
    39.6  Version: @VERSION@
    39.7 -Requires: razor expat zlib
    39.8 +Requires: razor expat zlib glib2
    39.9  Libs: -L${libdir} -lplover
   39.10  Cflags: -I${includedir}
    40.1 --- a/plover/razor.c	Fri Mar 23 20:29:50 2012 +0000
    40.2 +++ b/plover/razor.c	Sat Nov 15 19:04:45 2014 +0000
    40.3 @@ -1,7 +1,7 @@
    40.4  /*
    40.5   * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    40.6   * Copyright (C) 2008  Red Hat, Inc
    40.7 - * Copyright (C) 2009, 2011, 2012  J. Ali Harlow <ali@juiblex.co.uk>
    40.8 + * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    40.9   *
   40.10   * This program is free software; you can redistribute it and/or modify
   40.11   * it under the terms of the GNU General Public License as published by
   40.12 @@ -22,10 +22,14 @@
   40.13  #include <stdio.h>
   40.14  #include <stdarg.h>
   40.15  #include <string.h>
   40.16 +#include <errno.h>
   40.17  #include <unistd.h>
   40.18  #include <razor.h>
   40.19 +#include <glib.h>
   40.20 +#include <gio/gio.h>
   40.21  #include "config.h"
   40.22  #include "plover/plover.h"
   40.23 +#include "plover/transaction.h"
   40.24  
   40.25  static char *rpm_filename(const char *name,const char *version,const char *arch)
   40.26  {
   40.27 @@ -35,65 +39,7 @@
   40.28  	v++;
   40.29      else
   40.30  	v=version;
   40.31 -    return plover_strconcat(name,"-",v,".",arch,".rpm",NULL);
   40.32 -}
   40.33 -
   40.34 -struct razor_set *plover_relocate_packages(struct razor_set *set,
   40.35 -  const char *base,struct razor_relocations *relocations,
   40.36 -  struct razor_error **error)
   40.37 -{
   40.38 -    struct razor_importer *importer;
   40.39 -    struct razor_property_iterator *prop_iter;
   40.40 -    struct razor_package_iterator *pkg_iter;
   40.41 -    struct razor_file_iterator *file_iter;
   40.42 -    struct razor_package *package;
   40.43 -    struct razor_property *property;
   40.44 -    struct razor_rpm *rpm;
   40.45 -    struct razor_set *new;
   40.46 -    const char *name,*version,*arch,*summary,*desc,*url,*license;
   40.47 -    char *s,*file;
   40.48 -    uint32_t flags;
   40.49 -    importer=razor_importer_create();
   40.50 -    pkg_iter=razor_package_iterator_create(set);
   40.51 -    while (razor_package_iterator_next(pkg_iter,&package,RAZOR_DETAIL_NAME,
   40.52 -      &name,RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
   40.53 -      RAZOR_DETAIL_SUMMARY,&summary,RAZOR_DETAIL_DESCRIPTION,&desc,
   40.54 -      RAZOR_DETAIL_URL,&url,RAZOR_DETAIL_LICENSE,&license,RAZOR_DETAIL_LAST))
   40.55 -    {
   40.56 -	s=rpm_filename(name,version,arch);
   40.57 -	file=plover_strconcat(base,"/rpms/",s,NULL);
   40.58 -	free(s);
   40.59 -	rpm=razor_rpm_open(file,error);
   40.60 -	free(file);
   40.61 -	if (!rpm)
   40.62 -	{
   40.63 -	    razor_package_iterator_destroy(pkg_iter);
   40.64 -	    razor_importer_destroy(importer);
   40.65 -	    return NULL;
   40.66 -	}
   40.67 -	razor_relocations_set_rpm(relocations,rpm);
   40.68 -	razor_rpm_close(rpm);
   40.69 -	razor_importer_begin_package(importer,name,version,arch);
   40.70 -	razor_importer_add_details(importer,summary,desc,url,license);
   40.71 -	prop_iter=razor_property_iterator_create(set,package);
   40.72 -	while (razor_property_iterator_next(prop_iter,&property,&name,&flags,
   40.73 -	  &version))
   40.74 -	    razor_importer_add_property(importer,name,flags,version);
   40.75 -	razor_property_iterator_destroy(prop_iter);
   40.76 -	file_iter=razor_file_iterator_create(set,package,0);
   40.77 -	while (razor_file_iterator_next(file_iter,&name))
   40.78 -	{
   40.79 -	    name=razor_relocations_apply(relocations,name);
   40.80 -	    razor_importer_add_file(importer,name);
   40.81 -	}
   40.82 -	razor_file_iterator_destroy(file_iter);
   40.83 -	razor_importer_finish_package(importer);
   40.84 -    }
   40.85 -    razor_package_iterator_destroy(pkg_iter);
   40.86 -    new=razor_importer_finish(importer);
   40.87 -    if (new)
   40.88 -	razor_set_set_header_version(new,razor_set_get_header_version(set));
   40.89 -    return new;
   40.90 +    return g_strconcat(name,"-",v,".",arch,".rpm",NULL);
   40.91  }
   40.92  
   40.93  /*
   40.94 @@ -101,17 +47,20 @@
   40.95   * is met (in which case the action is consumed).
   40.96   */
   40.97  int plover_run_transaction(struct razor_transaction *trans,
   40.98 -  struct razor_install_iterator *ii,const char *base,const char *install_root,
   40.99 -  struct razor_set *system,struct razor_set *next,struct razor_atomic *atomic,
  40.100 -  struct razor_relocations *relocations,enum razor_stage_type stage)
  40.101 +  struct razor_install_iterator *ii,const char *install_root,
  40.102 +  struct razor_set *system,PloverPackageSet *next,PloverRepository *upstream,
  40.103 +  struct razor_atomic *atomic,struct razor_relocations *relocations,
  40.104 +  enum razor_stage_type stage,GCancellable *cancellable)
  40.105  {
  40.106 -    struct razor_package *package;
  40.107 +    struct razor_package *pkg;
  40.108      enum razor_install_action action;
  40.109      struct razor_rpm *rpm;
  40.110      struct razor_error *error=NULL;
  40.111      const char *name,*version,*arch;
  40.112 -    char *s,*file;
  40.113 +    gchar *t;
  40.114      int r,count;
  40.115 +    GError *tmp_error=NULL;
  40.116 +    PloverPackage *package;
  40.117      switch(stage)
  40.118      {
  40.119  	case RAZOR_STAGE_SCRIPTS_PRE:
  40.120 @@ -127,40 +76,41 @@
  40.121  	    /* Keep the compiler happy */
  40.122  	    break;
  40.123      }
  40.124 -    while (razor_install_iterator_next(ii,&package,&action,&count))
  40.125 +    while (razor_install_iterator_next(ii,&pkg,&action,&count))
  40.126      {
  40.127 +	if (g_cancellable_is_cancelled(cancellable))
  40.128 +	{
  40.129 +	    razor_atomic_abort(atomic,PLOVER_GENERAL_ERROR,
  40.130 +	      PLOVER_GENERAL_ERROR_CANCELLED,"Operation was cancelled");
  40.131 +	    return -1;
  40.132 +	}
  40.133  	if (action==RAZOR_INSTALL_ACTION_REMOVE)
  40.134  	{
  40.135 -	    razor_package_get_details(system,package,RAZOR_DETAIL_NAME,&name,
  40.136 +	    razor_package_get_details(system,pkg,RAZOR_DETAIL_NAME,&name,
  40.137  	      RAZOR_DETAIL_LAST);
  40.138  	    if (stage==RAZOR_STAGE_FILES)
  40.139  		printf("  Removing : %s ",name);
  40.140 -	    r=razor_package_remove(system,next,atomic,package,install_root,
  40.141 -	      count,stage);
  40.142 +	    r=razor_package_remove(system,plover_package_set_get_razor(next),
  40.143 +	      atomic,pkg,install_root,count,stage);
  40.144  	    if (stage==RAZOR_STAGE_FILES)
  40.145  		printf("\n");
  40.146  	}
  40.147  	else if (action==RAZOR_INSTALL_ACTION_ADD)
  40.148  	{
  40.149 -	    razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
  40.150 -	      RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
  40.151 -	      RAZOR_DETAIL_LAST);
  40.152 -	    s=rpm_filename(name,version,arch);
  40.153 -	    file=plover_strconcat(base,"/rpms/",s,NULL);
  40.154 -	    free(s);
  40.155 -	    rpm=razor_rpm_open(file,&error);
  40.156 -	    free(file);
  40.157 +	    package=plover_package_set_lookup(next,pkg);
  40.158 +	    rpm=plover_repository_open_rpm(upstream,package,&tmp_error);
  40.159  	    if (!rpm)
  40.160  	    {
  40.161 -		razor_atomic_abort(atomic,razor_error_get_msg(error));
  40.162 +		plover_propagate_g_error(&error,tmp_error);
  40.163 +		razor_atomic_propagate_error(atomic,error,NULL);
  40.164  		razor_error_free(error);
  40.165  		return -1;
  40.166  	    }
  40.167  	    if (stage==RAZOR_STAGE_FILES)
  40.168 -		printf("  Installing : %s ",name);
  40.169 +		printf("  Installing : %s ",plover_package_get_name(package));
  40.170  	    if (relocations)
  40.171  		razor_rpm_set_relocations(rpm,relocations);
  40.172 -	    razor_transaction_fixup_package(trans,package,rpm);
  40.173 +	    razor_transaction_fixup_package(trans,pkg,rpm);
  40.174  	    r=razor_rpm_install(rpm,atomic,install_root,1,stage);
  40.175  	    razor_rpm_close(rpm);
  40.176  	    if (stage==RAZOR_STAGE_FILES)
  40.177 @@ -174,9 +124,10 @@
  40.178  	    return -1;
  40.179  	else if (r)
  40.180  	{
  40.181 -	    razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
  40.182 -	      RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
  40.183 -	      RAZOR_DETAIL_LAST);
  40.184 +	    package=plover_package_set_lookup(next,pkg);
  40.185 +	    name=plover_package_get_name(package);
  40.186 +	    version=plover_package_get_version(package);
  40.187 +	    arch=plover_package_get_arch(package);
  40.188  	    /*
  40.189  	     * If a pre or preun script fails, then we should
  40.190  	     * treat that as a fatal error. post and postun
  40.191 @@ -185,10 +136,12 @@
  40.192  	     */
  40.193  	    if (stage==RAZOR_STAGE_SCRIPTS_PRE)
  40.194  	    {
  40.195 -		fprintf(stderr,
  40.196 -		  "error: %s(%s-%s.%s) scriptlet failed, exit status %d\n",
  40.197 -		  action==RAZOR_INSTALL_ACTION_ADD?"%pre":"%preun",
  40.198 -		  name,version,arch,r);
  40.199 +		t=g_strconcat(action==RAZOR_INSTALL_ACTION_ADD?
  40.200 +		  "%pre":"%preun","(",name,"-",version,".",arch,
  40.201 +		  ") scriptlet failed",NULL);
  40.202 +		fprintf(stderr,"error: %s, exit status %d\n",t,r);
  40.203 +		razor_atomic_abort(atomic,PLOVER_SCRIPTLET_ERROR,r,t);
  40.204 +		g_free(t);
  40.205  		return -1;
  40.206  	    }
  40.207  	    else
  40.208 @@ -201,339 +154,70 @@
  40.209      return 0;
  40.210  }
  40.211  
  40.212 -int plover_commit_transaction(struct razor_transaction *trans,const char *base,
  40.213 -  const char *install_root,struct razor_root *root,
  40.214 -  struct razor_relocations *relocations)
  40.215 +gboolean plover_install(const char *base,const char *prefix,char **pkgs,
  40.216 +  GError **error)
  40.217  {
  40.218 -    int r,retval;
  40.219 -    size_t pos;
  40.220 -    struct razor_set *system,*next,*set;
  40.221 -    struct razor_install_iterator *ii;
  40.222 -    struct razor_atomic *atomic;
  40.223 -    razor_transaction_resolve(trans);
  40.224 -    if (razor_transaction_describe(trans)>0)
  40.225 -	return -1;
  40.226 -    next=razor_transaction_commit(trans);
  40.227 -    system=razor_set_ref(razor_root_get_system_set(root));
  40.228 -    ii=razor_set_create_install_iterator(system,next);
  40.229 -    do
  40.230 -    {
  40.231 -	pos=razor_install_iterator_tell(ii);
  40.232 -	atomic=razor_atomic_open("package transaction");
  40.233 -	r=plover_run_transaction(trans,ii,base,install_root,system,next,atomic,
  40.234 -	  relocations,RAZOR_STAGE_SCRIPTS_PRE);
  40.235 -	if (r<0)
  40.236 -	    fprintf(stderr,"Transaction aborted\n");
  40.237 -	else
  40.238 -	{
  40.239 -	    razor_install_iterator_seek(ii,pos);
  40.240 -	    r=plover_run_transaction(trans,ii,base,install_root,system,next,
  40.241 -	      atomic,relocations,RAZOR_STAGE_FILES);
  40.242 -	    if (r==1)
  40.243 -	    {
  40.244 -		set=razor_install_iterator_commit_set(ii);
  40.245 -		razor_root_update(root,set,atomic);
  40.246 -		razor_set_unref(set);
  40.247 -	    }
  40.248 -	    else if (!r)
  40.249 -		razor_root_update(root,next,atomic);
  40.250 -	    retval=razor_atomic_commit(atomic);
  40.251 -	    if (retval)
  40.252 -		fprintf(stderr,"%s\n",razor_atomic_get_error_msg(atomic));
  40.253 -	    else
  40.254 -	    {
  40.255 -		razor_install_iterator_seek(ii,pos);
  40.256 -		plover_run_transaction(trans,ii,base,install_root,system,next,
  40.257 -		  atomic,relocations,RAZOR_STAGE_SCRIPTS_POST);
  40.258 -	    }
  40.259 -	}
  40.260 -	razor_atomic_destroy(atomic);
  40.261 -    } while(!retval && r==1);
  40.262 -    razor_set_unref(system);
  40.263 -    razor_set_unref(next);
  40.264 -    razor_install_iterator_destroy(ii);
  40.265 +    gboolean retval;
  40.266 +    PloverTransaction *transaction;
  40.267 +    transaction=plover_transaction_new_install(base,prefix,pkgs,error);
  40.268 +    if (!transaction)
  40.269 +	return FALSE;
  40.270 +    retval=plover_transaction_commit(transaction,NULL,error);
  40.271 +    g_object_unref(transaction);
  40.272      return retval;
  40.273  }
  40.274  
  40.275 -static int plover_mark_package_for_update(struct razor_transaction *trans,
  40.276 -  struct razor_set *set,const char *pkg)
  40.277 +gboolean plover_update(const char *base,const char *prefix,char **pkgs,
  40.278 +  GError **error)
  40.279  {
  40.280 -    struct razor_package_iterator *pi;
  40.281 -    struct razor_package *package;
  40.282 -    const char *name;
  40.283 -    int retval=-1;
  40.284 -    pi=razor_package_iterator_create(set);
  40.285 -    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
  40.286 -      RAZOR_DETAIL_LAST))
  40.287 +    gboolean retval;
  40.288 +    GError *tmp_error=NULL;
  40.289 +    PloverTransaction *transaction;
  40.290 +    transaction=plover_transaction_new_update(base,prefix,pkgs,&tmp_error);
  40.291 +    if (!transaction)
  40.292      {
  40.293 -	if (!strcmp(name,pkg))
  40.294 -	{
  40.295 -	    razor_transaction_update_package(trans,package);
  40.296 -	    retval=0;
  40.297 -	    break;
  40.298 -	}
  40.299 +	retval=g_error_matches(tmp_error,PLOVER_POSIX_ERROR,ENOENT);
  40.300 +	if (retval)
  40.301 +	    g_error_free(tmp_error);
  40.302 +	else
  40.303 +	    g_propagate_error(error,tmp_error);
  40.304      }
  40.305 -    razor_package_iterator_destroy(pi);
  40.306 +    else
  40.307 +    {
  40.308 +	retval=plover_transaction_commit(transaction,NULL,error);
  40.309 +	g_object_unref(transaction);
  40.310 +    }
  40.311      return retval;
  40.312  }
  40.313  
  40.314 -int plover_install(const char *base,const char *prefix,char **pkgs)
  40.315 +gboolean plover_remove(char **pkgs,GError **error)
  40.316  {
  40.317 -    int i,retval;
  40.318 -    char *s;
  40.319 -    char *install_root;
  40.320 -    struct razor_set *system,*set,*upstream;
  40.321 -    struct razor_transaction *trans;
  40.322 -    struct razor_relocations *relocations;
  40.323 -    struct razor_root *root;
  40.324 -    struct razor_error *error=NULL;
  40.325 -    install_root=getenv("RAZOR_ROOT");
  40.326 -    if (!install_root)
  40.327 -	install_root="";
  40.328 -    if (prefix)
  40.329 +    gboolean retval;
  40.330 +    GError *tmp_error=NULL;
  40.331 +    PloverTransaction *transaction;
  40.332 +    transaction=plover_transaction_new_remove(pkgs,&tmp_error);
  40.333 +    if (!transaction)
  40.334      {
  40.335 -	relocations=razor_relocations_create();
  40.336 -	razor_relocations_add(relocations,"/usr",prefix);
  40.337 -    }
  40.338 -    else
  40.339 -	relocations=NULL;
  40.340 -    root=razor_root_open(install_root,NULL);
  40.341 -    if (!root)
  40.342 -    {
  40.343 -	if (razor_root_create(install_root,&error))
  40.344 -	    root=NULL;
  40.345 +	retval=g_error_matches(tmp_error,PLOVER_POSIX_ERROR,ENOENT);
  40.346 +	if (retval)
  40.347 +	{
  40.348 +	    g_error_free(tmp_error);
  40.349 +	    if (pkgs)
  40.350 +	    {
  40.351 +		g_set_error(error,PLOVER_GENERAL_ERROR,
  40.352 +		  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[0],
  40.353 +		  "Package not found");
  40.354 +		retval=FALSE;
  40.355 +	    }
  40.356 +	}
  40.357  	else
  40.358 -	    root=razor_root_open(install_root,&error);
  40.359 -	if (!root)
  40.360 -	{
  40.361 -	    fprintf(stderr,"%s\n",razor_error_get_msg(error));
  40.362 -	    razor_error_free(error);
  40.363 -	    if (relocations)
  40.364 -		razor_relocations_destroy(relocations);
  40.365 -	    return -1;
  40.366 -	}
  40.367 -    }
  40.368 -    system=razor_root_get_system_set(root);
  40.369 -    if (!system)
  40.370 -    {
  40.371 -	fprintf(stderr,"Internal error: No system set\n");
  40.372 -	razor_root_close(root);
  40.373 -	if (relocations)
  40.374 -	    razor_relocations_destroy(relocations);
  40.375 -	return -1;
  40.376 -    }
  40.377 -    s=plover_strconcat(base,"/repodata",NULL);
  40.378 -    if (s)
  40.379 -    {
  40.380 -	retval=chdir(s);
  40.381 -	if (retval<0)
  40.382 -	    perror(s);
  40.383 +	    g_propagate_error(error,tmp_error);
  40.384      }
  40.385      else
  40.386      {
  40.387 -	fprintf(stderr,"Not enough memory\n");
  40.388 -	retval=-1;
  40.389 +	retval=plover_transaction_commit(transaction,NULL,error);
  40.390 +	g_object_unref(transaction);
  40.391      }
  40.392 -    free(s);
  40.393 -    if (retval<0)
  40.394 -    {
  40.395 -	razor_root_close(root);
  40.396 -	if (relocations)
  40.397 -	    razor_relocations_destroy(relocations);
  40.398 -	return -1;
  40.399 -    }
  40.400 -    set=plover_razor_set_create_from_yum(base);
  40.401 -    if (set)
  40.402 -    {
  40.403 -	upstream=plover_relocate_packages(set,base,relocations,&error);
  40.404 -	if (!upstream)
  40.405 -	{
  40.406 -	    fprintf(stderr,"%s\n",razor_error_get_msg(error));
  40.407 -	    razor_error_free(error);
  40.408 -	}
  40.409 -	razor_set_unref(set);
  40.410 -    }
  40.411 -    else
  40.412 -	upstream=NULL;
  40.413 -    if (!upstream)
  40.414 -    {
  40.415 -	razor_root_close(root);
  40.416 -	if (relocations)
  40.417 -	    razor_relocations_destroy(relocations);
  40.418 -	return -1;
  40.419 -    }
  40.420 -    trans=razor_transaction_create(system,upstream);
  40.421 -    razor_set_unref(upstream);
  40.422 -    for(i=0;pkgs[i];i++)
  40.423 -	if (plover_mark_package_for_update(trans,system,pkgs[i]) &&
  40.424 -	  plover_mark_package_for_update(trans,upstream,pkgs[i]))
  40.425 -	{
  40.426 -	    fprintf(stderr,"%s: Package not found\n",pkgs[i]);
  40.427 -	    retval=-1;
  40.428 -	    break;
  40.429 -	}
  40.430 -    if (!retval)
  40.431 -	retval=plover_commit_transaction(trans,base,install_root,root,
  40.432 -	  relocations);
  40.433 -    razor_transaction_destroy(trans);
  40.434 -    razor_root_close(root);
  40.435 -    if (relocations)
  40.436 -	razor_relocations_destroy(relocations);
  40.437 -    return retval;
  40.438 -}
  40.439 -
  40.440 -int plover_update(const char *base,const char *prefix,char **pkgs)
  40.441 -{
  40.442 -    int i,retval;
  40.443 -    char *install_root,*s;
  40.444 -    struct razor_set *system,*set,*upstream;
  40.445 -    struct razor_transaction *trans;
  40.446 -    struct razor_relocations *relocations;
  40.447 -    struct razor_root *root;
  40.448 -    struct razor_error *error=NULL;
  40.449 -    install_root=getenv("RAZOR_ROOT");
  40.450 -    if (!install_root)
  40.451 -	install_root="";
  40.452 -    if (prefix)
  40.453 -    {
  40.454 -	relocations=razor_relocations_create();
  40.455 -	razor_relocations_add(relocations,"/usr",prefix);
  40.456 -    }
  40.457 -    else
  40.458 -	relocations=NULL;
  40.459 -    root=razor_root_open(install_root,&error);
  40.460 -    if (!root)
  40.461 -    {
  40.462 -	fprintf(stderr,"%s\n",razor_error_get_msg(error));
  40.463 -	razor_error_free(error);
  40.464 -	if (relocations)
  40.465 -	    razor_relocations_destroy(relocations);
  40.466 -	return 0;
  40.467 -    }
  40.468 -    system=razor_root_get_system_set(root);
  40.469 -    s=plover_strconcat(base,"/repodata",NULL);
  40.470 -    if (s)
  40.471 -    {
  40.472 -	retval=chdir(s);
  40.473 -	if (retval)
  40.474 -	    perror(s);
  40.475 -    }
  40.476 -    else
  40.477 -    {
  40.478 -	fprintf(stderr,"Not enough memory");
  40.479 -	retval=-1;
  40.480 -    }
  40.481 -    free(s);
  40.482 -    if (retval)
  40.483 -    {
  40.484 -	razor_root_close(root);
  40.485 -	if (relocations)
  40.486 -	    razor_relocations_destroy(relocations);
  40.487 -	return -1;
  40.488 -    }
  40.489 -    set=plover_razor_set_create_from_yum(base);
  40.490 -    if (set)
  40.491 -    {
  40.492 -	upstream=plover_relocate_packages(set,base,relocations,&error);
  40.493 -	if (!upstream)
  40.494 -	{
  40.495 -	    fprintf(stderr,"%s\n",razor_error_get_msg(error));
  40.496 -	    razor_error_free(error);
  40.497 -	}
  40.498 -	razor_set_unref(set);
  40.499 -    }
  40.500 -    else
  40.501 -	upstream=NULL;
  40.502 -    if (!upstream)
  40.503 -    {
  40.504 -	razor_root_close(root);
  40.505 -	if (relocations)
  40.506 -	    razor_relocations_destroy(relocations);
  40.507 -	return -1;
  40.508 -    }
  40.509 -    trans=razor_transaction_create(system,upstream);
  40.510 -    razor_set_unref(upstream);
  40.511 -    if (pkgs)
  40.512 -	for(i=0;pkgs[i];i++)
  40.513 -	{
  40.514 -	    if (plover_mark_package_for_update(trans,system,pkgs[i]))
  40.515 -	    {
  40.516 -		fprintf(stderr,"%s: Package not found\n",pkgs[i]);
  40.517 -		retval=-1;
  40.518 -		break;
  40.519 -	    }
  40.520 -	}
  40.521 -    else
  40.522 -	razor_transaction_update_all(trans);
  40.523 -    if (!retval)
  40.524 -	retval=plover_commit_transaction(trans,base,install_root,root,
  40.525 -	  relocations);
  40.526 -    razor_transaction_destroy(trans);
  40.527 -    razor_root_close(root);
  40.528 -    if (relocations)
  40.529 -	razor_relocations_destroy(relocations);
  40.530 -    return retval;
  40.531 -}
  40.532 -
  40.533 -static int plover_mark_packages_for_removal(struct razor_transaction *trans,
  40.534 -  struct razor_set *set,const char *pkg)
  40.535 -{
  40.536 -    struct razor_package_iterator *pi;
  40.537 -    struct razor_package *package;
  40.538 -    const char *name;
  40.539 -    int retval=pkg?-1:0;
  40.540 -    pi=razor_package_iterator_create(set);
  40.541 -    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
  40.542 -      RAZOR_DETAIL_LAST))
  40.543 -    {
  40.544 -	if (!pkg || !strcmp(name,pkg))
  40.545 -	{
  40.546 -	    razor_transaction_remove_package(trans,package);
  40.547 -	    retval=0;
  40.548 -	}
  40.549 -    }
  40.550 -    razor_package_iterator_destroy(pi);
  40.551 -    return retval;
  40.552 -}
  40.553 -
  40.554 -int plover_remove(char **pkgs)
  40.555 -{
  40.556 -    int i,retval=0;
  40.557 -    char *install_root;
  40.558 -    struct razor_set *system,*upstream;
  40.559 -    struct razor_transaction *trans;
  40.560 -    struct razor_root *root;
  40.561 -    struct razor_error *error=NULL;
  40.562 -    install_root=getenv("RAZOR_ROOT");
  40.563 -    if (!install_root)
  40.564 -	install_root="";
  40.565 -    root=razor_root_open(install_root,&error);
  40.566 -    if (!root)
  40.567 -    {
  40.568 -	fprintf(stderr,"%s\n",razor_error_get_msg(error));
  40.569 -	razor_error_free(error);
  40.570 -	return 0;
  40.571 -    }
  40.572 -    system=razor_root_get_system_set(root);
  40.573 -    upstream=razor_set_create_without_root();
  40.574 -    trans=razor_transaction_create(system,upstream);
  40.575 -    razor_set_unref(upstream);
  40.576 -    if (pkgs)
  40.577 -	for(i=0;pkgs[i];i++)
  40.578 -	{
  40.579 -	    if (plover_mark_packages_for_removal(trans,system,pkgs[i]))
  40.580 -	    {
  40.581 -		fprintf(stderr,"%s: Package not found\n",pkgs[i]);
  40.582 -		retval=-1;
  40.583 -		break;
  40.584 -	    }
  40.585 -	}
  40.586 -    else
  40.587 -	plover_mark_packages_for_removal(trans,system,NULL);
  40.588 -    if (!retval)
  40.589 -	retval=plover_commit_transaction(trans,NULL,install_root,root,NULL);
  40.590 -    razor_transaction_destroy(trans);
  40.591 -    razor_root_close(root);
  40.592      return retval;
  40.593  }
  40.594  
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/plover/repository.c	Sat Nov 15 19:04:45 2014 +0000
    41.3 @@ -0,0 +1,168 @@
    41.4 +/*
    41.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    41.6 + *
    41.7 + * This program is free software; you can redistribute it and/or modify
    41.8 + * it under the terms of the GNU General Public License as published by
    41.9 + * the Free Software Foundation; either version 2 of the License, or
   41.10 + * (at your option) any later version.
   41.11 + *
   41.12 + * This program is distributed in the hope that it will be useful,
   41.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.15 + * GNU General Public License for more details.
   41.16 + *
   41.17 + * You should have received a copy of the GNU General Public License along
   41.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   41.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   41.20 + */
   41.21 +
   41.22 +#include "config.h"
   41.23 +#include <stdlib.h>
   41.24 +#include <string.h>
   41.25 +#include <glib-object.h>
   41.26 +#include <razor.h>
   41.27 +#include <plover/plover.h>
   41.28 +#include <plover/repository.h>
   41.29 +
   41.30 +G_DEFINE_TYPE(PloverRepository,plover_repository,G_TYPE_OBJECT);
   41.31 +
   41.32 +typedef struct _PloverRepositoryPrivate {
   41.33 +    PloverPackageSet *set;
   41.34 +    gchar **filenames;
   41.35 +} PloverRepositoryPrivate;
   41.36 +
   41.37 +#define PLOVER_REPOSITORY_GET_PRIVATE(obj)\
   41.38 +				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
   41.39 +				  PLOVER_TYPE_REPOSITORY,\
   41.40 +				  PloverRepositoryPrivate)
   41.41 +
   41.42 +static void plover_repository_finalize(GObject *obj)
   41.43 +{
   41.44 +    PloverRepositoryPrivate *priv=PLOVER_REPOSITORY_GET_PRIVATE(obj);
   41.45 +    g_strfreev(priv->filenames);
   41.46 +    if (G_OBJECT_CLASS(plover_repository_parent_class)->finalize)
   41.47 +	G_OBJECT_CLASS(plover_repository_parent_class)->finalize(obj);
   41.48 +}
   41.49 +
   41.50 +static void plover_repository_dispose(GObject *obj)
   41.51 +{
   41.52 +    PloverRepositoryPrivate *priv=PLOVER_REPOSITORY_GET_PRIVATE(obj);
   41.53 +    g_clear_object(&priv->set);
   41.54 +    if (G_OBJECT_CLASS(plover_repository_parent_class)->dispose)
   41.55 +	G_OBJECT_CLASS(plover_repository_parent_class)->dispose(obj);
   41.56 +}
   41.57 +
   41.58 +static void plover_repository_class_init(PloverRepositoryClass *klass)
   41.59 +{
   41.60 +    GObjectClass *oclass=G_OBJECT_CLASS(klass);
   41.61 +    oclass->finalize=plover_repository_finalize;
   41.62 +    oclass->dispose=plover_repository_dispose;
   41.63 +    g_type_class_add_private(klass,sizeof(PloverRepositoryPrivate));
   41.64 +}
   41.65 +
   41.66 +static void plover_repository_init(PloverRepository *repository)
   41.67 +{
   41.68 +}
   41.69 +
   41.70 +PloverRepository *plover_repository_new_from_files(const char **filenames,
   41.71 +  GError **error)
   41.72 +{
   41.73 +    PloverPackageSet *set;
   41.74 +    PloverRepository *repository;
   41.75 +    PloverRepositoryPrivate *priv;
   41.76 +    set=plover_package_set_new_from_rpms(filenames,error);
   41.77 +    if (!set)
   41.78 +	return NULL;
   41.79 +    repository=g_object_new(PLOVER_TYPE_REPOSITORY,NULL);
   41.80 +    priv=PLOVER_REPOSITORY_GET_PRIVATE(repository);
   41.81 +    priv->filenames=g_strdupv((gchar **)filenames);
   41.82 +    priv->set=set;
   41.83 +    return repository;
   41.84 +}
   41.85 +
   41.86 +static char *rpm_filename(const char *name,const char *version,const char *arch)
   41.87 +{
   41.88 +    const char *v;
   41.89 +    v=strchr(version,':');            /* Skip epoch */
   41.90 +    if (v)
   41.91 +	v++;
   41.92 +    else
   41.93 +	v=version;
   41.94 +    return g_strconcat(name,"-",v,".",arch,".rpm",NULL);
   41.95 +}
   41.96 +
   41.97 +PloverRepository *plover_repository_new_from_yum(const char *base,
   41.98 +  GError **error)
   41.99 +{
  41.100 +    char *s;
  41.101 +    const char *name,*version,*arch;
  41.102 +    GPtrArray *filenames;
  41.103 +    struct razor_set *imported;
  41.104 +    struct razor_package *package;
  41.105 +    struct razor_package_iterator *pi;
  41.106 +    PloverPackageSet *set;
  41.107 +    PloverRepository *repository;
  41.108 +    PloverRepositoryPrivate *priv;
  41.109 +    imported=plover_razor_set_create_from_yum(base,error);
  41.110 +    if (!imported)
  41.111 +	return NULL;
  41.112 +    set=plover_package_set_new_from_razor(imported);
  41.113 +    razor_set_unref(imported);
  41.114 +    repository=g_object_new(PLOVER_TYPE_REPOSITORY,NULL);
  41.115 +    priv=PLOVER_REPOSITORY_GET_PRIVATE(repository);
  41.116 +    filenames=g_ptr_array_new();
  41.117 +    pi=razor_package_iterator_create(plover_package_set_get_razor(set));
  41.118 +    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
  41.119 +      RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,RAZOR_DETAIL_LAST))
  41.120 +    {
  41.121 +	s=rpm_filename(name,version,arch);
  41.122 +	g_ptr_array_add(filenames,g_build_filename(base,"rpms",s,NULL));
  41.123 +	free(s);
  41.124 +    }
  41.125 +    razor_package_iterator_destroy(pi);
  41.126 +    g_ptr_array_add(filenames,NULL);
  41.127 +    priv->filenames=(gchar **)g_ptr_array_free(filenames,FALSE);
  41.128 +    priv->set=set;
  41.129 +    return repository;
  41.130 +}
  41.131 +
  41.132 +PloverPackageSet *
  41.133 +  plover_repository_get_package_set(PloverRepository *repository)
  41.134 +{
  41.135 +    PloverRepositoryPrivate *priv;
  41.136 +    g_return_val_if_fail(PLOVER_IS_REPOSITORY(repository),NULL);
  41.137 +    priv=PLOVER_REPOSITORY_GET_PRIVATE(repository);
  41.138 +    return priv->set;
  41.139 +}
  41.140 +
  41.141 +struct razor_rpm *plover_repository_open_rpm(PloverRepository *repository,
  41.142 +  PloverPackage *package,GError **error)
  41.143 +{
  41.144 +    int nth;
  41.145 +    struct razor_rpm *rpm;
  41.146 +    struct razor_error *tmp_error=NULL;
  41.147 +    PloverRepositoryPrivate *priv;
  41.148 +    PloverPackage *internal;
  41.149 +    g_return_val_if_fail(PLOVER_IS_REPOSITORY(repository),NULL);
  41.150 +    g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
  41.151 +    priv=PLOVER_REPOSITORY_GET_PRIVATE(repository);
  41.152 +    nth=g_slist_index(plover_package_set_get_packages(priv->set),package);
  41.153 +    if (nth<0)
  41.154 +    {
  41.155 +	internal=plover_package_set_find_matching(priv->set,package);
  41.156 +	nth=g_slist_index(plover_package_set_get_packages(priv->set),internal);
  41.157 +    }
  41.158 +    if (nth<0)
  41.159 +    {
  41.160 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  41.161 +	  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,
  41.162 +	  "%s-%s.%s: Package not in repository",
  41.163 +	  plover_package_get_name(package),plover_package_get_version(package),
  41.164 +	  plover_package_get_arch(package));
  41.165 +	return NULL;
  41.166 +    }
  41.167 +    rpm=razor_rpm_open(priv->filenames[nth],&tmp_error);
  41.168 +    if (!rpm)
  41.169 +	plover_propagate_razor_error(error,tmp_error);
  41.170 +    return rpm;
  41.171 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/plover/repository.h	Sat Nov 15 19:04:45 2014 +0000
    42.3 @@ -0,0 +1,49 @@
    42.4 +#ifndef __PLOVER_REPOSITORY_H__
    42.5 +#define __PLOVER_REPOSITORY_H__
    42.6 +
    42.7 +#include <razor.h>
    42.8 +#include <glib-object.h>
    42.9 +#include <gio/gio.h>
   42.10 +
   42.11 +G_BEGIN_DECLS
   42.12 +
   42.13 +#define PLOVER_TYPE_REPOSITORY	plover_repository_get_type()
   42.14 +#define PLOVER_REPOSITORY(obj)	G_TYPE_CHECK_INSTANCE_CAST(obj,\
   42.15 +				  PLOVER_TYPE_REPOSITORY,PloverRepository)
   42.16 +#define PLOVER_REPOSITORY_CLASS(klass)\
   42.17 +				G_TYPE_CHECK_CLASS_CAST(klass,\
   42.18 +				  PLOVER_TYPE_REPOSITORY,PloverRepositoryClass)
   42.19 +#define PLOVER_IS_REPOSITORY(obj)\
   42.20 +				G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   42.21 +				  PLOVER_TYPE_REPOSITORY)
   42.22 +#define PLOVER_IS_REPOSITORY_CLASS(klass)\
   42.23 +				G_TYPE_CHECK_CLASS_TYPE(obj,\
   42.24 +				  PLOVER_TYPE_REPOSITORY)
   42.25 +#define PLOVER_REPOSITORY_GET_CLASS(obj)\
   42.26 +				G_TYPE_INSTANCE_GET_CLASS(obj,\
   42.27 +				  PLOVER_TYPE_REPOSITORY,PloverRepositoryClass)
   42.28 +
   42.29 +typedef struct _PloverRepository {
   42.30 +    GObject parent_instance;
   42.31 +} PloverRepository;
   42.32 +
   42.33 +typedef struct _PloverRepositoryClass {
   42.34 +    GObjectClass parent_class;
   42.35 +} PloverRepositoryClass;
   42.36 +
   42.37 +#include <plover/package.h>
   42.38 +#include <plover/packageset.h>
   42.39 +
   42.40 +GType plover_repository_get_type(void) G_GNUC_CONST;
   42.41 +PloverRepository *plover_repository_new_from_files(const char **filenames,
   42.42 +  GError **error);
   42.43 +PloverRepository *plover_repository_new_from_yum(const char *base,
   42.44 +  GError **error);
   42.45 +PloverPackageSet *
   42.46 +  plover_repository_get_package_set(PloverRepository *repository);
   42.47 +struct razor_rpm *plover_repository_open_rpm(PloverRepository *repository,
   42.48 +  PloverPackage *package,GError **error);
   42.49 +
   42.50 +G_END_DECLS
   42.51 +
   42.52 +#endif /* __PLOVER_REPOSITORY_H__ */
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/plover/transaction.c	Sat Nov 15 19:04:45 2014 +0000
    43.3 @@ -0,0 +1,722 @@
    43.4 +/*
    43.5 + * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    43.6 + *
    43.7 + * This program is free software; you can redistribute it and/or modify
    43.8 + * it under the terms of the GNU General Public License as published by
    43.9 + * the Free Software Foundation; either version 2 of the License, or
   43.10 + * (at your option) any later version.
   43.11 + *
   43.12 + * This program is distributed in the hope that it will be useful,
   43.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.15 + * GNU General Public License for more details.
   43.16 + *
   43.17 + * You should have received a copy of the GNU General Public License along
   43.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   43.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   43.20 + */
   43.21 +
   43.22 +#include "config.h"
   43.23 +#include <stdlib.h>
   43.24 +#include <string.h>
   43.25 +#include <errno.h>
   43.26 +#include <unistd.h>
   43.27 +#include <glib-object.h>
   43.28 +#include "plover/transaction.h"
   43.29 +#include "plover/plover.h"
   43.30 +
   43.31 +G_DEFINE_TYPE(PloverTransaction,plover_transaction,G_TYPE_OBJECT);
   43.32 +
   43.33 +enum {
   43.34 +    STATUS_CHANGED=0,
   43.35 +    N_SIGNALS
   43.36 +};
   43.37 +
   43.38 +static guint signals[N_SIGNALS];
   43.39 +
   43.40 +static void plover_transaction_finalize(PloverTransaction *transaction)
   43.41 +{
   43.42 +    g_free(transaction->base);
   43.43 +    g_free(transaction->prefix);
   43.44 +    g_free(transaction->unsatisfied);
   43.45 +    if (transaction->trans)
   43.46 +	razor_transaction_destroy(transaction->trans);
   43.47 +    if (transaction->relocations)
   43.48 +	razor_relocations_destroy(transaction->relocations);
   43.49 +    if (transaction->install_iterator)
   43.50 +	razor_install_iterator_destroy(transaction->install_iterator);
   43.51 +    if (transaction->next)
   43.52 +	razor_set_unref(transaction->next);
   43.53 +    if (transaction->system)
   43.54 +	razor_set_unref(transaction->system);
   43.55 +}
   43.56 +
   43.57 +static void plover_transaction_dispose(PloverTransaction *transaction)
   43.58 +{
   43.59 +    g_clear_object(&transaction->installed);
   43.60 +    g_clear_object(&transaction->relocated);
   43.61 +    g_clear_object(&transaction->upstream);
   43.62 +}
   43.63 +
   43.64 +static void plover_transaction_class_init(PloverTransactionClass *klass)
   43.65 +{
   43.66 +    GObjectClass *gobject_class=G_OBJECT_CLASS(klass);
   43.67 +    gobject_class->finalize=(void (*)(GObject *))plover_transaction_finalize;
   43.68 +    gobject_class->dispose=(void (*)(GObject *))plover_transaction_dispose;
   43.69 +    signals[STATUS_CHANGED]=g_signal_new("status-changed",
   43.70 +      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,0,NULL,NULL,
   43.71 +      g_cclosure_marshal_VOID__STRING,G_TYPE_NONE,1,G_TYPE_STRING);
   43.72 +}
   43.73 +
   43.74 +static void plover_transaction_init(PloverTransaction *transaction)
   43.75 +{
   43.76 +}
   43.77 +
   43.78 +gboolean plover_transaction_resolve(PloverTransaction *transaction,
   43.79 +  GError **error)
   43.80 +{
   43.81 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
   43.82 +    if (!(transaction->flags&PLOVER_TRANSACTION_RESOLVED))
   43.83 +    {
   43.84 +	razor_transaction_resolve(transaction->trans);
   43.85 +	transaction->flags|=PLOVER_TRANSACTION_RESOLVED;
   43.86 +	g_free(transaction->unsatisfied);
   43.87 +	transaction->unsatisfied=NULL;
   43.88 +	if (razor_transaction_describe(transaction->trans)>0)
   43.89 +	    transaction->flags|=PLOVER_TRANSACTION_UNSATISFIED;
   43.90 +    }
   43.91 +    if (transaction->flags&PLOVER_TRANSACTION_UNSATISFIED)
   43.92 +    {
   43.93 +	g_set_error(error,PLOVER_GENERAL_ERROR,
   43.94 +	  PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET,
   43.95 +	  "Package requirements not met");
   43.96 +	return FALSE;
   43.97 +    }
   43.98 +    return TRUE;
   43.99 +}
  43.100 +
  43.101 +static void plover_transaction_unsatisfied_callback(const char *requirement,
  43.102 +  struct razor_package *package,const char *name,const char *version,
  43.103 +  const char *arch,void *data)
  43.104 +{
  43.105 +    GString *string=data;
  43.106 +    g_string_append_printf(string,"%s is needed by %s-%s.%s\n",requirement,name,
  43.107 +      version,arch);
  43.108 +}
  43.109 +
  43.110 +const char *plover_transaction_get_unsatisfied(PloverTransaction *transaction)
  43.111 +{
  43.112 +    GString *unsatisfied;
  43.113 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),NULL);
  43.114 +    if (plover_transaction_resolve(transaction,NULL))
  43.115 +	return NULL;
  43.116 +    else if (!transaction->unsatisfied)
  43.117 +    {
  43.118 +	unsatisfied=g_string_new(NULL);
  43.119 +	if (!razor_transaction_unsatisfied(transaction->trans,
  43.120 +	  plover_transaction_unsatisfied_callback,unsatisfied))
  43.121 +	    /* Impossible */
  43.122 +	    g_string_assign(unsatisfied,
  43.123 +	      "Unknown package requirements unsatisfied");
  43.124 +	transaction->unsatisfied=g_string_free(unsatisfied,FALSE);
  43.125 +    }
  43.126 +    return transaction->unsatisfied;
  43.127 +}
  43.128 +
  43.129 +struct razor_set *plover_transaction_get_system_set(
  43.130 +  PloverTransaction *transaction)
  43.131 +{
  43.132 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),NULL);
  43.133 +    if (!transaction->system && transaction->installed)
  43.134 +    {
  43.135 +	transaction->system=
  43.136 +	  plover_package_set_get_razor(transaction->installed);
  43.137 +	if (transaction->system)
  43.138 +	    razor_set_ref(transaction->system);
  43.139 +    }
  43.140 +    return transaction->system;
  43.141 +}
  43.142 +
  43.143 +struct razor_set *plover_transaction_get_next_set(
  43.144 +  PloverTransaction *transaction,GError **error)
  43.145 +{
  43.146 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),NULL);
  43.147 +    if (!transaction->next)
  43.148 +    {
  43.149 +	if (!plover_transaction_resolve(transaction,error))
  43.150 +	    return NULL;
  43.151 +	transaction->next=razor_transaction_commit(transaction->trans);
  43.152 +    }
  43.153 +    return transaction->next;
  43.154 +}
  43.155 +
  43.156 +struct razor_install_iterator *plover_transaction_get_install_iterator(
  43.157 +  PloverTransaction *transaction,GError **error)
  43.158 +{
  43.159 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),NULL);
  43.160 +    if (!transaction->install_iterator)
  43.161 +    {
  43.162 +	if (!plover_transaction_get_next_set(transaction,error))
  43.163 +	    return NULL;
  43.164 +	(void)plover_transaction_get_system_set(transaction);
  43.165 +	transaction->install_iterator=
  43.166 +	  razor_set_create_install_iterator(transaction->system,
  43.167 +	  transaction->next);
  43.168 +    }
  43.169 +    razor_install_iterator_rewind(transaction->install_iterator);
  43.170 +    return transaction->install_iterator;
  43.171 +}
  43.172 +
  43.173 +gboolean plover_transaction_commit(PloverTransaction *transaction,
  43.174 +  GCancellable *cancellable,GError **error)
  43.175 +{
  43.176 +    int r;
  43.177 +    gboolean retval;
  43.178 +    size_t pos;
  43.179 +    struct razor_set *set;
  43.180 +    struct razor_install_iterator *ii;
  43.181 +    struct razor_atomic *atomic;
  43.182 +    PloverPackageSet *next;
  43.183 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.184 +    if (g_cancellable_set_error_if_cancelled(cancellable,error))
  43.185 +	return FALSE;
  43.186 +    ii=plover_transaction_get_install_iterator(transaction,error);
  43.187 +    if (!ii)
  43.188 +	return FALSE;
  43.189 +    do
  43.190 +    {
  43.191 +	if (g_cancellable_set_error_if_cancelled(cancellable,error))
  43.192 +	    return FALSE;
  43.193 +	pos=razor_install_iterator_tell(ii);
  43.194 +	g_signal_emit(transaction,signals[STATUS_CHANGED],0,
  43.195 +	  "Running pre-transaction scripts");
  43.196 +	atomic=razor_atomic_open("package transaction");
  43.197 +	next=plover_package_set_new_from_razor(transaction->next);
  43.198 +	r=plover_run_transaction(transaction->trans,ii,
  43.199 +	  plover_package_set_get_install_root(transaction->installed),
  43.200 +	  transaction->system,next,transaction->upstream,atomic,
  43.201 +	  transaction->relocations,RAZOR_STAGE_SCRIPTS_PRE,cancellable);
  43.202 +	if (r<0)
  43.203 +	{
  43.204 +	    g_signal_emit(transaction,signals[STATUS_CHANGED],0,
  43.205 +	      "Failed in pre-transaction scripts");
  43.206 +	    plover_propagate_razor_error_dup(error,
  43.207 +	      razor_atomic_get_error(atomic));
  43.208 +	    razor_atomic_destroy(atomic);
  43.209 +	    g_object_unref(next);
  43.210 +	    return FALSE;
  43.211 +	}
  43.212 +	else
  43.213 +	{
  43.214 +	    g_signal_emit(transaction,signals[STATUS_CHANGED],0,
  43.215 +	      "Unpacking files");
  43.216 +	    razor_install_iterator_seek(ii,pos);
  43.217 +	    r=plover_run_transaction(transaction->trans,ii,
  43.218 +	      plover_package_set_get_install_root(transaction->installed),
  43.219 +	      transaction->system,next,transaction->upstream,
  43.220 +	      atomic,transaction->relocations,RAZOR_STAGE_FILES,
  43.221 +#if RAZOR_HAVE_ATOMIC_ROLLBACK
  43.222 +	      cancellable);
  43.223 +#else
  43.224 +	      NULL);
  43.225 +#endif
  43.226 +	    if (r==1)
  43.227 +	    {
  43.228 +		set=razor_install_iterator_commit_set(ii);
  43.229 +		plover_package_set_update(transaction->installed,set,atomic);
  43.230 +		razor_set_unref(set);
  43.231 +	    }
  43.232 +	    else if (!r)
  43.233 +		plover_package_set_update(transaction->installed,
  43.234 +		  transaction->next,atomic);
  43.235 +	    retval=!razor_atomic_commit(atomic);
  43.236 +	    if (!retval)
  43.237 +	    {
  43.238 +		g_signal_emit(transaction,signals[STATUS_CHANGED],0,
  43.239 +		  "Failed to unpack all files correctly");
  43.240 +		plover_propagate_razor_error_dup(error,
  43.241 +		  razor_atomic_get_error(atomic));
  43.242 +	    }
  43.243 +	    else
  43.244 +	    {
  43.245 +		g_signal_emit(transaction,signals[STATUS_CHANGED],0,
  43.246 +		  "Running post-transaction scripts");
  43.247 +		razor_install_iterator_seek(ii,pos);
  43.248 +		plover_run_transaction(transaction->trans,ii,
  43.249 +		  plover_package_set_get_install_root(transaction->installed),
  43.250 +		  transaction->system,next,transaction->upstream,
  43.251 +		  atomic,transaction->relocations,RAZOR_STAGE_SCRIPTS_POST,
  43.252 +		  NULL);
  43.253 +	    }
  43.254 +	}
  43.255 +	razor_atomic_destroy(atomic);
  43.256 +	g_object_unref(next);
  43.257 +    } while(retval && r==1);
  43.258 +    g_signal_emit(transaction,signals[STATUS_CHANGED],0,"Completed");
  43.259 +    return retval;
  43.260 +}
  43.261 +
  43.262 +static void plover_transaction_commit_async_thread(GTask *task,
  43.263 +  gpointer source_object,gpointer task_data,GCancellable *cancellable)
  43.264 +{
  43.265 +    PloverTransaction *transaction=source_object;
  43.266 +    GError *error=NULL;
  43.267 +    if (!plover_transaction_commit(transaction,cancellable,&error))
  43.268 +	g_task_return_error(task,error);
  43.269 +    else
  43.270 +	g_task_return_boolean(task,TRUE);
  43.271 +    g_object_unref(task);
  43.272 +}
  43.273 +
  43.274 +void plover_transaction_commit_async(PloverTransaction *transaction,
  43.275 +  GCancellable *cancellable,GAsyncReadyCallback callback,gpointer user_data)
  43.276 +{
  43.277 +    GTask *task;
  43.278 +    g_return_if_fail(PLOVER_IS_TRANSACTION(transaction));
  43.279 +    task=g_task_new(transaction,cancellable,callback,user_data);
  43.280 +    g_task_run_in_thread(task,plover_transaction_commit_async_thread);
  43.281 +}
  43.282 +
  43.283 +gboolean plover_transaction_commit_finish(PloverTransaction *transaction,
  43.284 +  GAsyncResult *result,GError **error)
  43.285 +{
  43.286 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.287 +    g_return_val_if_fail(g_task_is_valid(result,transaction),FALSE);
  43.288 +    return g_task_propagate_boolean(G_TASK(result),error);
  43.289 +}
  43.290 +
  43.291 +static int plover_mark_package_for_update(struct razor_transaction *trans,
  43.292 +  struct razor_set *set,const char *pkg)
  43.293 +{
  43.294 +    struct razor_package_iterator *pi;
  43.295 +    struct razor_package *package;
  43.296 +    const char *name;
  43.297 +    int retval=-1;
  43.298 +    pi=razor_package_iterator_create(set);
  43.299 +    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
  43.300 +      RAZOR_DETAIL_LAST))
  43.301 +    {
  43.302 +	if (!strcmp(name,pkg))
  43.303 +	{
  43.304 +	    razor_transaction_update_package(trans,package);
  43.305 +	    retval=0;
  43.306 +	    break;
  43.307 +	}
  43.308 +    }
  43.309 +    razor_package_iterator_destroy(pi);
  43.310 +    return retval;
  43.311 +}
  43.312 +
  43.313 +PloverTransaction *plover_transaction_new(void)
  43.314 +{
  43.315 +    return PLOVER_TRANSACTION(g_object_new(PLOVER_TYPE_TRANSACTION,NULL));
  43.316 +}
  43.317 +
  43.318 +void plover_transaction_set_prefix(PloverTransaction *transaction,
  43.319 +  const char *prefix)
  43.320 +{
  43.321 +    g_return_if_fail(PLOVER_IS_TRANSACTION(transaction));
  43.322 +    g_return_if_fail(transaction->upstream == NULL);
  43.323 +    if (!g_strcmp0(prefix,transaction->prefix))
  43.324 +	return;
  43.325 +    if (transaction->relocations)
  43.326 +	razor_relocations_destroy(transaction->relocations);
  43.327 +    g_free(transaction->prefix);
  43.328 +    if (prefix)
  43.329 +    {
  43.330 +	transaction->relocations=razor_relocations_create();
  43.331 +	razor_relocations_add(transaction->relocations,"/usr",prefix);
  43.332 +    }
  43.333 +    else
  43.334 +	transaction->relocations=NULL;
  43.335 +    transaction->prefix=g_strdup(prefix);
  43.336 +}
  43.337 +
  43.338 +void plover_transaction_set_installed(PloverTransaction *transaction,
  43.339 +  PloverPackageSet *installed)
  43.340 +{
  43.341 +    g_return_if_fail(PLOVER_IS_TRANSACTION(transaction));
  43.342 +    g_return_if_fail(PLOVER_IS_PACKAGE_SET(installed));
  43.343 +    if (transaction->installed)
  43.344 +	g_object_unref(transaction->installed);
  43.345 +    transaction->installed=g_object_ref(installed);
  43.346 +}
  43.347 +
  43.348 +gboolean plover_transaction_root_open(PloverTransaction *transaction,
  43.349 +  const char *install_root,GError **error)
  43.350 +{
  43.351 +    PloverPackageSet *installed;
  43.352 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.353 +    if (!install_root)
  43.354 +	install_root=g_getenv("RAZOR_ROOT");
  43.355 +    if (!install_root)
  43.356 +	install_root="";
  43.357 +    if (transaction->installed && !g_strcmp0(install_root,
  43.358 +      plover_package_set_get_install_root(transaction->installed)))
  43.359 +	return TRUE;
  43.360 +    installed=plover_package_set_new();
  43.361 +    if (!plover_package_set_open(installed,install_root,TRUE,error))
  43.362 +    {
  43.363 +	g_object_unref(installed);
  43.364 +	return FALSE;
  43.365 +    }
  43.366 +    if (transaction->installed)
  43.367 +	g_object_unref(transaction->installed);
  43.368 +    transaction->installed=installed;
  43.369 +    return TRUE;
  43.370 +}
  43.371 +
  43.372 +struct razor_set *plover_transaction_import_yum(PloverTransaction *transaction,
  43.373 +  const char *base,GError **error)
  43.374 +{
  43.375 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),NULL);
  43.376 +    g_return_val_if_fail(transaction->base == NULL,NULL);
  43.377 +    transaction->base=g_strdup(base);
  43.378 +    return plover_razor_set_create_from_yum(base,error);
  43.379 +}
  43.380 +
  43.381 +gboolean plover_transaction_set_upstream(PloverTransaction *transaction,
  43.382 +  PloverRepository *upstream,GError **error)
  43.383 +{
  43.384 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.385 +    g_return_val_if_fail(PLOVER_IS_REPOSITORY(upstream),FALSE);
  43.386 +    g_return_val_if_fail(transaction->upstream == NULL,FALSE);
  43.387 +    transaction->relocated=plover_package_set_new_from_repository(upstream,
  43.388 +      transaction->relocations,error);
  43.389 +    if (transaction->relocated)
  43.390 +	transaction->upstream=g_object_ref(upstream);
  43.391 +    return !!transaction->relocated;
  43.392 +}
  43.393 +
  43.394 +gboolean
  43.395 +  plover_transaction_set_upstream_from_yum(PloverTransaction *transaction,
  43.396 +  const char *base,GError **error)
  43.397 +{
  43.398 +    gboolean retval;
  43.399 +    PloverRepository *upstream;
  43.400 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.401 +    g_return_val_if_fail(transaction->upstream == NULL,FALSE);
  43.402 +    upstream=plover_repository_new_from_yum(base,error);
  43.403 +    if (!upstream)
  43.404 +	return FALSE;
  43.405 +    retval=plover_transaction_set_upstream(transaction,upstream,error);
  43.406 +    g_object_unref(upstream);
  43.407 +    return retval;
  43.408 +}
  43.409 +
  43.410 +gboolean plover_transaction_install(PloverTransaction *transaction,
  43.411 +  char **pkgs,GError **error)
  43.412 +{
  43.413 +    int i;
  43.414 +    struct razor_set *system,*upstream;
  43.415 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.416 +    g_return_val_if_fail(transaction->upstream != NULL,FALSE);
  43.417 +    g_return_val_if_fail(transaction->trans == NULL,FALSE);
  43.418 +    if (!plover_transaction_root_open(transaction,NULL,error))
  43.419 +	return FALSE;
  43.420 +    system=plover_transaction_get_system_set(transaction);
  43.421 +    if (!system)
  43.422 +    {
  43.423 +	g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  43.424 +	  "Internal error: No system set");
  43.425 +	return FALSE;
  43.426 +    }
  43.427 +    upstream=plover_package_set_get_razor(transaction->relocated);
  43.428 +    transaction->trans=razor_transaction_create(system,upstream);
  43.429 +    for(i=0;pkgs[i];i++)
  43.430 +	if (plover_mark_package_for_update(transaction->trans,system,pkgs[i]) &&
  43.431 +	  plover_mark_package_for_update(transaction->trans,upstream,pkgs[i]))
  43.432 +	{
  43.433 +	    g_set_error(error,PLOVER_GENERAL_ERROR,
  43.434 +	      PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[i],
  43.435 +	      "Package not found");
  43.436 +	    razor_transaction_destroy(transaction->trans);
  43.437 +	    transaction->trans=NULL;
  43.438 +	    return FALSE;
  43.439 +	    break;
  43.440 +	}
  43.441 +    return TRUE;
  43.442 +}
  43.443 +
  43.444 +gboolean plover_transaction_update(PloverTransaction *transaction,
  43.445 +  char **pkgs,GError **error)
  43.446 +{
  43.447 +    int i;
  43.448 +    struct razor_set *system,*upstream;
  43.449 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.450 +    g_return_val_if_fail(transaction->upstream != NULL,FALSE);
  43.451 +    g_return_val_if_fail(transaction->trans == NULL,FALSE);
  43.452 +    if (!plover_transaction_root_open(transaction,NULL,error))
  43.453 +	return FALSE;
  43.454 +    system=plover_transaction_get_system_set(transaction);
  43.455 +    if (!system)
  43.456 +    {
  43.457 +	g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  43.458 +	  "Internal error: No system set");
  43.459 +	return FALSE;
  43.460 +    }
  43.461 +    upstream=plover_package_set_get_razor(transaction->relocated);
  43.462 +    transaction->trans=razor_transaction_create(system,upstream);
  43.463 +    if (!pkgs)
  43.464 +	razor_transaction_update_all(transaction->trans);
  43.465 +    else
  43.466 +	for(i=0;pkgs[i];i++)
  43.467 +	    if (plover_mark_package_for_update(transaction->trans,system,
  43.468 +	      pkgs[i]))
  43.469 +	    {
  43.470 +		g_set_error(error,PLOVER_GENERAL_ERROR,
  43.471 +		  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[i],
  43.472 +		  "Package not found");
  43.473 +		razor_transaction_destroy(transaction->trans);
  43.474 +		transaction->trans=NULL;
  43.475 +		return FALSE;
  43.476 +		break;
  43.477 +	    }
  43.478 +    return TRUE;
  43.479 +}
  43.480 +
  43.481 +PloverTransaction *plover_transaction_new_install(const char *base,
  43.482 +  const char *prefix,char **pkgs,GError **error)
  43.483 +{
  43.484 +    PloverTransaction *transaction;
  43.485 +    transaction=plover_transaction_new();
  43.486 +    plover_transaction_set_prefix(transaction,prefix);
  43.487 +    if (!plover_transaction_set_upstream_from_yum(transaction,base,error))
  43.488 +    {
  43.489 +	g_object_unref(transaction);
  43.490 +	return NULL;
  43.491 +    }
  43.492 +    if (!plover_transaction_install(transaction,pkgs,error))
  43.493 +    {
  43.494 +	g_object_unref(transaction);
  43.495 +	return NULL;
  43.496 +    }
  43.497 +    return transaction;
  43.498 +}
  43.499 +
  43.500 +PloverTransaction *plover_transaction_new_update(const char *base,
  43.501 +  const char *prefix,char **pkgs,GError **error)
  43.502 +{
  43.503 +    PloverTransaction *transaction;
  43.504 +    transaction=plover_transaction_new();
  43.505 +    plover_transaction_set_prefix(transaction,prefix);
  43.506 +    if (!plover_transaction_set_upstream_from_yum(transaction,base,error))
  43.507 +    {
  43.508 +	g_object_unref(transaction);
  43.509 +	return NULL;
  43.510 +    }
  43.511 +    if (!plover_transaction_update(transaction,pkgs,error))
  43.512 +    {
  43.513 +	g_object_unref(transaction);
  43.514 +	return NULL;
  43.515 +    }
  43.516 +    return transaction;
  43.517 +}
  43.518 +
  43.519 +static int plover_mark_packages_for_removal(struct razor_transaction *trans,
  43.520 +  struct razor_set *set,const char *pkg)
  43.521 +{
  43.522 +    struct razor_package_iterator *pi;
  43.523 +    struct razor_package *package;
  43.524 +    const char *name;
  43.525 +    int retval=pkg?-1:0;
  43.526 +    pi=razor_package_iterator_create(set);
  43.527 +    while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name,
  43.528 +      RAZOR_DETAIL_LAST))
  43.529 +    {
  43.530 +	if (!pkg || !strcmp(name,pkg))
  43.531 +	{
  43.532 +	    razor_transaction_remove_package(trans,package);
  43.533 +	    retval=0;
  43.534 +	}
  43.535 +    }
  43.536 +    razor_package_iterator_destroy(pi);
  43.537 +    return retval;
  43.538 +}
  43.539 +
  43.540 +gboolean plover_transaction_remove(PloverTransaction *transaction,
  43.541 +  char **pkgs,GError **error)
  43.542 +{
  43.543 +    int i;
  43.544 +    struct razor_set *system,*empty;
  43.545 +    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
  43.546 +    g_return_val_if_fail(transaction->trans == NULL,FALSE);
  43.547 +    if (!plover_transaction_root_open(transaction,NULL,error))
  43.548 +	return FALSE;
  43.549 +    system=plover_transaction_get_system_set(transaction);
  43.550 +    if (!system)
  43.551 +    {
  43.552 +	g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
  43.553 +	  "Internal error: No system set");
  43.554 +	return FALSE;
  43.555 +    }
  43.556 +    empty=razor_set_create_without_root();
  43.557 +    transaction->trans=razor_transaction_create(system,empty);
  43.558 +    razor_set_unref(empty);
  43.559 +    if (!pkgs)
  43.560 +	plover_mark_packages_for_removal(transaction->trans,system,NULL);
  43.561 +    else
  43.562 +	for(i=0;pkgs[i];i++)
  43.563 +	    if (plover_mark_packages_for_removal(transaction->trans,system,
  43.564 +	      pkgs[i]))
  43.565 +	    {
  43.566 +		g_set_error(error,PLOVER_GENERAL_ERROR,
  43.567 +		  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[i],
  43.568 +		  "Package not found");
  43.569 +		razor_transaction_destroy(transaction->trans);
  43.570 +		transaction->trans=NULL;
  43.571 +		return FALSE;
  43.572 +		break;
  43.573 +	    }
  43.574 +    return TRUE;
  43.575 +}
  43.576 +
  43.577 +PloverTransaction *plover_transaction_new_remove(char **pkgs,GError **error)
  43.578 +{
  43.579 +    PloverTransaction *transaction;
  43.580 +    transaction=plover_transaction_new();
  43.581 +    if (!plover_transaction_remove(transaction,pkgs,error))
  43.582 +    {
  43.583 +	g_object_unref(transaction);
  43.584 +	return NULL;
  43.585 +    }
  43.586 +    return transaction;
  43.587 +}
  43.588 +
  43.589 +static GList *plover_what_requires(struct razor_set *set,const char *ref_name)
  43.590 +{
  43.591 +    const char *name,*version;
  43.592 +    uint32_t flags;
  43.593 +    GList *list=NULL;
  43.594 +    struct razor_property *property;
  43.595 +    struct razor_package *package;
  43.596 +    struct razor_package_iterator *what_requires;
  43.597 +    struct razor_property_iterator *all_props;
  43.598 +    all_props=razor_property_iterator_create(set,NULL);
  43.599 +    while (razor_property_iterator_next(all_props,&property,&name,&flags,
  43.600 +      &version))
  43.601 +    {
  43.602 +	if ((flags&RAZOR_PROPERTY_TYPE_MASK)!=RAZOR_PROPERTY_REQUIRES)
  43.603 +	    continue;
  43.604 +	if (strcmp(name,ref_name))
  43.605 +	    continue;
  43.606 +	what_requires=razor_package_iterator_create_for_property(set,property);
  43.607 +	while(razor_package_iterator_next(what_requires,&package,
  43.608 +	  RAZOR_DETAIL_LAST))
  43.609 +	    list=g_list_prepend(list,package);
  43.610 +	razor_package_iterator_destroy(what_requires);
  43.611 +    }
  43.612 +    razor_property_iterator_destroy(all_props);
  43.613 +    return list;
  43.614 +}
  43.615 +
  43.616 +/* 
  43.617 + * Warning: This code is untested and probably wrong.
  43.618 + */
  43.619 +PloverTransaction *plover_transaction_new_remove_with_leaves(char **pkgs,
  43.620 +  GError **error)
  43.621 +{
  43.622 +    int i,changed,is_leaf;
  43.623 +    uint32_t flags;
  43.624 +    const char *install_root;
  43.625 +    const char *name,*version,*maybe_unused_name;
  43.626 +    struct razor_set *system,*upstream;
  43.627 +    struct razor_transaction *trans;
  43.628 +    PloverPackageSet *installed;
  43.629 +    PloverTransaction *transaction;
  43.630 +    if (!pkgs)
  43.631 +	return plover_transaction_new_remove(NULL,error);
  43.632 +    installed=plover_package_set_new();
  43.633 +    install_root=g_getenv("RAZOR_ROOT");
  43.634 +    if (!install_root)
  43.635 +	install_root="";
  43.636 +    if (!plover_package_set_open(installed,install_root,TRUE,error))
  43.637 +    {
  43.638 +	g_object_unref(installed);
  43.639 +	return NULL;
  43.640 +    }
  43.641 +    system=plover_package_set_get_razor(installed);
  43.642 +    struct plover_vector *package_names;
  43.643 +    GList *to_remove,*lnk,*what_requires;
  43.644 +    struct razor_package *package,*maybe_unused_package;
  43.645 +    struct razor_property *property;
  43.646 +    struct razor_package_query *query;
  43.647 +    struct razor_package_iterator *all_packages,*removed,*maybe_unused;
  43.648 +    struct razor_property_iterator *removed_props;
  43.649 +    package_names=plover_vector_new();
  43.650 +    for(i=0;pkgs[i];i++)
  43.651 +	plover_vector_append(package_names,pkgs[i]);
  43.652 +    to_remove=NULL;
  43.653 +    all_packages=razor_package_iterator_create(system);
  43.654 +    while (razor_package_iterator_next(all_packages,&package,
  43.655 +      RAZOR_DETAIL_NAME,&name,RAZOR_DETAIL_LAST))
  43.656 +	if (plover_vector_remove(package_names,name))
  43.657 +	    to_remove=g_list_prepend(to_remove,package);
  43.658 +    razor_package_iterator_destroy(all_packages);
  43.659 +    if (package_names->len)
  43.660 +    {
  43.661 +	g_set_error(error,PLOVER_GENERAL_ERROR,
  43.662 +	  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",
  43.663 +	  package_names->strings[0],"Package not found");
  43.664 +	plover_vector_free(package_names);
  43.665 +	g_list_free(to_remove);
  43.666 +	g_object_unref(installed);
  43.667 +	return NULL;
  43.668 +    }
  43.669 +    plover_vector_free(package_names);
  43.670 +    do
  43.671 +    {
  43.672 +	changed=FALSE;
  43.673 +	query=razor_package_query_create(system);
  43.674 +	for(lnk=to_remove;lnk;lnk=lnk->next)
  43.675 +	    razor_package_query_add_package(query,lnk->data);
  43.676 +	removed=razor_package_query_finish(query);
  43.677 +	while(razor_package_iterator_next(removed,&package,RAZOR_DETAIL_LAST))
  43.678 +	{
  43.679 +	    removed_props=razor_property_iterator_create(system,package);
  43.680 +	    while (razor_property_iterator_next(removed_props,&property,&name,
  43.681 +	      &flags,&version))
  43.682 +	    {
  43.683 +		if ((flags&RAZOR_PROPERTY_TYPE_MASK)!=RAZOR_PROPERTY_REQUIRES)
  43.684 +		    continue;
  43.685 +		maybe_unused=razor_package_iterator_create_for_property(system,
  43.686 +		  property);
  43.687 +		while(razor_package_iterator_next(maybe_unused,
  43.688 +		  &maybe_unused_package,RAZOR_DETAIL_NAME,&maybe_unused_name,
  43.689 +		  RAZOR_DETAIL_LAST))
  43.690 +		{
  43.691 +		    if (g_list_find(to_remove,maybe_unused_package))
  43.692 +			continue;
  43.693 +		    is_leaf=TRUE;
  43.694 +		    what_requires=plover_what_requires(system,
  43.695 +		      maybe_unused_name);
  43.696 +		    for(lnk=what_requires;lnk;lnk=lnk->next)
  43.697 +			if (!g_list_find(to_remove,lnk->data))
  43.698 +			{
  43.699 +			    is_leaf=FALSE;
  43.700 +			    break;
  43.701 +			}
  43.702 +		    g_list_free(what_requires);
  43.703 +		    if (is_leaf)
  43.704 +		    {
  43.705 +			to_remove=g_list_prepend(to_remove,
  43.706 +			  maybe_unused_package);
  43.707 +			changed=TRUE;
  43.708 +		    }
  43.709 +		}
  43.710 +		razor_package_iterator_destroy(maybe_unused);
  43.711 +	    }
  43.712 +	    razor_property_iterator_destroy(removed_props);
  43.713 +	}
  43.714 +	razor_package_iterator_destroy(removed);
  43.715 +    } while(changed);
  43.716 +    upstream=razor_set_create_without_root();
  43.717 +    trans=razor_transaction_create(system,upstream);
  43.718 +    razor_set_unref(upstream);
  43.719 +    for(lnk=to_remove;lnk;lnk=lnk->next)
  43.720 +	razor_transaction_remove_package(trans,lnk->data);
  43.721 +    transaction=plover_transaction_new();
  43.722 +    transaction->trans=trans;
  43.723 +    transaction->installed=installed;
  43.724 +    return transaction;
  43.725 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/plover/transaction.h	Sat Nov 15 19:04:45 2014 +0000
    44.3 @@ -0,0 +1,87 @@
    44.4 +#ifndef __PLOVER_TRANSACTION_H__
    44.5 +#define __PLOVER_TRANSACTION_H__
    44.6 +
    44.7 +#include <razor.h>
    44.8 +#include <glib-object.h>
    44.9 +#include <gio/gio.h>
   44.10 +#include <plover/packageset.h>
   44.11 +
   44.12 +G_BEGIN_DECLS
   44.13 +
   44.14 +#define PLOVER_TYPE_TRANSACTION		plover_transaction_get_type()
   44.15 +#define PLOVER_TRANSACTION(obj)		G_TYPE_CHECK_INSTANCE_CAST(obj,\
   44.16 +					  PLOVER_TYPE_TRANSACTION,\
   44.17 +					  PloverTransaction)
   44.18 +#define PLOVER_IS_TRANSACTION(obj)	G_TYPE_CHECK_INSTANCE_TYPE(obj,\
   44.19 +					  PLOVER_TYPE_TRANSACTION)
   44.20 +
   44.21 +typedef enum {
   44.22 +    PLOVER_TRANSACTION_RESOLVED=1<<0,
   44.23 +    PLOVER_TRANSACTION_UNSATISFIED=1<<1,
   44.24 +} PloverTransactionFlags;
   44.25 +
   44.26 +typedef struct _PloverTransaction {
   44.27 +    GObject parent_instance;
   44.28 +    PloverTransactionFlags flags;
   44.29 +    struct razor_transaction *trans;
   44.30 +    char *prefix;
   44.31 +    char *base;
   44.32 +    char *install_root;
   44.33 +    char *unsatisfied;
   44.34 +    PloverPackageSet *installed,*relocated;
   44.35 +    PloverRepository *upstream;
   44.36 +    struct razor_relocations *relocations;
   44.37 +    struct razor_set *next,*system;
   44.38 +    struct razor_install_iterator *install_iterator;
   44.39 +} PloverTransaction;
   44.40 +
   44.41 +typedef struct _PloverTransactionClass {
   44.42 +    GObjectClass parent_class;
   44.43 +} PloverTransactionClass;
   44.44 +
   44.45 +GType plover_transaction_get_type(void) G_GNUC_CONST;
   44.46 +void plover_transaction_commit_async(PloverTransaction *transaction,
   44.47 +  GCancellable *cancellable,GAsyncReadyCallback callback,gpointer user_data);
   44.48 +gboolean plover_transaction_commit_finish(PloverTransaction *transaction,
   44.49 +  GAsyncResult *result,GError **error);
   44.50 +PloverTransaction *plover_transaction_new();
   44.51 +void plover_transaction_set_prefix(PloverTransaction *transaction,
   44.52 +  const char *prefix);
   44.53 +void plover_transaction_set_installed(PloverTransaction *transaction,
   44.54 +  PloverPackageSet *installed);
   44.55 +gboolean plover_transaction_root_open(PloverTransaction *transaction,
   44.56 +  const char *install_root,GError **error);
   44.57 +struct razor_set *plover_transaction_import_yum(PloverTransaction *transaction,
   44.58 +  const char *base,GError **error);
   44.59 +gboolean plover_transaction_set_upstream(PloverTransaction *transaction,
   44.60 +  PloverRepository *upstream,GError **error);
   44.61 +gboolean
   44.62 +  plover_transaction_set_upstream_from_yum(PloverTransaction *transaction,
   44.63 +  const char *base,GError **error);
   44.64 +gboolean plover_transaction_install(PloverTransaction *transaction,
   44.65 +  char **pkgs,GError **error);
   44.66 +PloverTransaction *plover_transaction_new_install(const char *base,
   44.67 +  const char *prefix,char **pkgs,GError **error);
   44.68 +gboolean plover_transaction_update(PloverTransaction *transaction,
   44.69 +  char **pkgs,GError **error);
   44.70 +PloverTransaction *plover_transaction_new_update(const char *base,
   44.71 +  const char *prefix,char **pkgs,GError **error);
   44.72 +gboolean plover_transaction_remove(PloverTransaction *transaction,
   44.73 +  char **pkgs,GError **error);
   44.74 +PloverTransaction *plover_transaction_new_remove(char **pkgs,
   44.75 +  GError **error);
   44.76 +gboolean plover_transaction_resolve(PloverTransaction *transaction,
   44.77 +  GError **error);
   44.78 +const char *plover_transaction_get_unsatisfied(PloverTransaction *transaction);
   44.79 +struct razor_set *plover_transaction_get_system_set(
   44.80 +  PloverTransaction *transaction);
   44.81 +struct razor_set *plover_transaction_get_next_set(
   44.82 +  PloverTransaction *transaction,GError **error);
   44.83 +struct razor_install_iterator *plover_transaction_get_install_iterator(
   44.84 +  PloverTransaction *transaction,GError **error);
   44.85 +gboolean plover_transaction_commit(PloverTransaction *transaction,
   44.86 +  GCancellable *cancellable,GError **error);
   44.87 +void plover_transaction_commit_async(PloverTransaction *transaction,
   44.88 +  GCancellable *cancellable,GAsyncReadyCallback callback,gpointer user_data);
   44.89 +
   44.90 +#endif /* __PLOVER_TRANSACTION_H__ */
    45.1 --- a/plover/util.c	Fri Mar 23 20:29:50 2012 +0000
    45.2 +++ b/plover/util.c	Sat Nov 15 19:04:45 2014 +0000
    45.3 @@ -1,5 +1,5 @@
    45.4  /*
    45.5 - * Copyright (C) 2009, 2011  J. Ali Harlow <ali@juiblex.co.uk>
    45.6 + * Copyright (C) 2009, 2011, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    45.7   *
    45.8   * This program is free software; you can redistribute it and/or modify
    45.9   * it under the terms of the GNU General Public License as published by
   45.10 @@ -27,37 +27,7 @@
   45.11  #include "config.h"
   45.12  #include "plover.h"
   45.13  
   45.14 -char *plover_strconcat(const char *string,...)
   45.15 -{
   45.16 -    va_list ap,aq;
   45.17 -    size_t n;
   45.18 -    char *result=NULL,*t;
   45.19 -    const char *s;
   45.20 -    if (string)
   45.21 -    {
   45.22 -	va_start(ap,string);
   45.23 -	va_copy(aq,ap);
   45.24 -	n=strlen(string);
   45.25 -	while((s=va_arg(aq,const char *)))
   45.26 -	    n+=strlen(s);
   45.27 -	va_end(aq);
   45.28 -	result=malloc(n+1);
   45.29 -	if (result)
   45.30 -	{
   45.31 -	    strcpy(result,string);
   45.32 -	    t=result+strlen(result);
   45.33 -	    while((s=va_arg(ap,const char *)))
   45.34 -	    {
   45.35 -		strcpy(t,s);
   45.36 -		t+=strlen(t);
   45.37 -	    }
   45.38 -	}
   45.39 -	va_end(ap);
   45.40 -    }
   45.41 -    return result;
   45.42 -}
   45.43 -
   45.44 -char *plover_default_prefix_for_vendor(const char *vendor)
   45.45 +gchar *plover_default_prefix_for_vendor(const char *vendor)
   45.46  {
   45.47  #ifdef WIN32
   45.48      /*
   45.49 @@ -83,12 +53,59 @@
   45.50  	  buf);
   45.51  	program_files=buf;
   45.52      }
   45.53 -    return plover_strconcat(program_files,"\\",vendor?vendor:"Plover",NULL);
   45.54 +    return g_strconcat(program_files,"\\",vendor?vendor:"Plover",NULL);
   45.55  #else
   45.56      return NULL;
   45.57  #endif
   45.58  }
   45.59  
   45.60 +gchar *plover_pre_install_prefix(void)
   45.61 +{
   45.62 +#ifdef WIN32
   45.63 +    {
   45.64 +	HRESULT result;
   45.65 +	HKEY key;
   45.66 +	DWORD type,nb;
   45.67 +	int len;
   45.68 +	gunichar2 *str2;
   45.69 +	gchar *root=NULL;
   45.70 +	result=RegOpenKeyW(HKEY_LOCAL_MACHINE,L"Software\\Plover",&key);
   45.71 +	if (result==ERROR_SUCCESS)
   45.72 +	{
   45.73 +	    result=RegQueryValueExW(key,L"Root",0,&type,0,&nb);
   45.74 +	    if (result==ERROR_SUCCESS && type==REG_SZ)
   45.75 +	    {
   45.76 +		str2=malloc(nb);
   45.77 +		result=RegQueryValueExW(key,L"Root",0,NULL,(void *)str2,&nb);
   45.78 +		len=nb/2;
   45.79 +		if (!str2[len-1])       /* Cope with unterminated strings */
   45.80 +		    len--;
   45.81 +		root=g_utf16_to_utf8(str2,len,NULL,NULL,NULL);
   45.82 +		free(str2);
   45.83 +	    }
   45.84 +	    RegCloseKey(key);
   45.85 +	}
   45.86 +	if (!root)
   45.87 +	{
   45.88 +	    root=plover_default_prefix_for_vendor("Plover Root");
   45.89 +	    result=RegCreateKeyExW(HKEY_LOCAL_MACHINE,L"Software\\Plover",0,
   45.90 +	      NULL,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,NULL,&key,NULL);
   45.91 +	    if (result==ERROR_SUCCESS)
   45.92 +	    {
   45.93 +		str2=g_utf8_to_utf16(root,-1,NULL,NULL,NULL);
   45.94 +		RegSetValueExW(key,L"Root",0,REG_SZ,(void *)str2,
   45.95 +		  (strlen(root)+1)*sizeof(gunichar2));
   45.96 +		g_free(str2);
   45.97 +		RegCloseKey(key);
   45.98 +	    }
   45.99 +	}
  45.100 +	return root;
  45.101 +    }
  45.102 +#else
  45.103 +    return g_strdup("/var/lib/plover/root");
  45.104 +#endif
  45.105 +}
  45.106 +
  45.107  /*
  45.108   * Get the directory containing the program executable.
  45.109   */
  45.110 @@ -119,3 +136,80 @@
  45.111  	return strdup(".");
  45.112  #endif
  45.113  }
  45.114 +
  45.115 +G_DEFINE_QUARK(plover-razor-error-quark,plover_razor_error)
  45.116 +G_DEFINE_QUARK(plover-mswin-error-quark,plover_mswin_error)
  45.117 +G_DEFINE_QUARK(plover-posix-error-quark,plover_posix_error)
  45.118 +G_DEFINE_QUARK(plover-zlib-error-quark,plover_zlib_error)
  45.119 +
  45.120 +void plover_propagate_razor_error_dup(GError **dest,struct razor_error *src)
  45.121 +{
  45.122 +    GQuark domain;
  45.123 +    int code;
  45.124 +    if (dest)
  45.125 +    {
  45.126 +	code=razor_error_get_code(src);
  45.127 +	switch(razor_error_get_domain(src))
  45.128 +	{
  45.129 +	    case RAZOR_GENERAL_ERROR:
  45.130 +		domain=PLOVER_RAZOR_ERROR;
  45.131 +		break;
  45.132 +	    case RAZOR_POSIX_ERROR:
  45.133 +		domain=PLOVER_POSIX_ERROR;
  45.134 +		break;
  45.135 +	    case RAZOR_MSWIN_ERROR:
  45.136 +		domain=PLOVER_MSWIN_ERROR;
  45.137 +		break;
  45.138 +	    case RAZOR_ZLIB_ERROR:
  45.139 +		domain=PLOVER_ZLIB_ERROR;
  45.140 +		break;
  45.141 +	    case PLOVER_GENERAL_ERROR:
  45.142 +		if (code==PLOVER_GENERAL_ERROR_CANCELLED)
  45.143 +		{
  45.144 +		    domain=G_IO_ERROR;
  45.145 +		    code=G_IO_ERROR_CANCELLED;
  45.146 +		    break;
  45.147 +		}
  45.148 +		/* else fall though */
  45.149 +	    default:
  45.150 +		domain=PLOVER_RAZOR_ERROR;
  45.151 +		code=RAZOR_GENERAL_ERROR_FAILED;
  45.152 +	}
  45.153 +	*dest=g_error_new_literal(domain,code,razor_error_get_msg(src));
  45.154 +    }
  45.155 +}
  45.156 +
  45.157 +void plover_propagate_razor_error(GError **dest,struct razor_error *src)
  45.158 +{
  45.159 +    plover_propagate_razor_error_dup(dest,src);
  45.160 +    razor_error_free(src);
  45.161 +}
  45.162 +
  45.163 +void plover_propagate_g_error(struct razor_error **dest,GError *src)
  45.164 +{
  45.165 +    int domain,code;
  45.166 +    if (dest)
  45.167 +    {
  45.168 +	code=src->code;
  45.169 +	if (src->domain==PLOVER_RAZOR_ERROR)
  45.170 +	    domain=RAZOR_GENERAL_ERROR;
  45.171 +	else if (src->domain==PLOVER_POSIX_ERROR)
  45.172 +	    domain=RAZOR_POSIX_ERROR;
  45.173 +	else if (src->domain==PLOVER_MSWIN_ERROR)
  45.174 +	    domain=RAZOR_MSWIN_ERROR;
  45.175 +	else if (src->domain==PLOVER_ZLIB_ERROR)
  45.176 +	    domain=RAZOR_ZLIB_ERROR;
  45.177 +	else if (src->domain==G_IO_ERROR && code==G_IO_ERROR_CANCELLED)
  45.178 +	{
  45.179 +	    domain=PLOVER_GENERAL_ERROR;
  45.180 +	    code=PLOVER_GENERAL_ERROR_CANCELLED;
  45.181 +	}
  45.182 +	else
  45.183 +	{
  45.184 +	    domain=RAZOR_GENERAL_ERROR;
  45.185 +	    code=RAZOR_GENERAL_ERROR_FAILED;
  45.186 +	}
  45.187 +	*dest=razor_error_new_str(domain,code,NULL,src->message);
  45.188 +    }
  45.189 +    g_error_free(src);
  45.190 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/plover/vector.c	Sat Nov 15 19:04:45 2014 +0000
    46.3 @@ -0,0 +1,130 @@
    46.4 +/*
    46.5 + * Copyright (C) 2009, 2014  J. Ali Harlow <ali@juiblex.co.uk>
    46.6 + *
    46.7 + * This program is free software; you can redistribute it and/or modify
    46.8 + * it under the terms of the GNU General Public License as published by
    46.9 + * the Free Software Foundation; either version 2 of the License, or
   46.10 + * (at your option) any later version.
   46.11 + *
   46.12 + * This program is distributed in the hope that it will be useful,
   46.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   46.15 + * GNU General Public License for more details.
   46.16 + *
   46.17 + * You should have received a copy of the GNU General Public License along
   46.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   46.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   46.20 + */
   46.21 +
   46.22 +#include <stdlib.h>
   46.23 +#include <string.h>
   46.24 +#include "config.h"
   46.25 +#include "plover.h"
   46.26 +
   46.27 +struct plover_vector *plover_vector_new(void)
   46.28 +{
   46.29 +    struct plover_vector *vector;
   46.30 +    vector=malloc(sizeof(*vector));
   46.31 +    vector->len=0;
   46.32 +    vector->alloc=16;
   46.33 +    vector->strings=calloc(vector->alloc,sizeof(char *));
   46.34 +    return vector;
   46.35 +}
   46.36 +
   46.37 +struct plover_vector *plover_vector_dup(struct plover_vector *old)
   46.38 +{
   46.39 +    int i;
   46.40 +    struct plover_vector *vector;
   46.41 +    vector=malloc(sizeof(*vector));
   46.42 +    vector->len=old->len;
   46.43 +    vector->alloc=old->alloc;
   46.44 +    vector->strings=calloc(vector->alloc,sizeof(char *));
   46.45 +    for(i=0;i<old->len;i++)
   46.46 +	vector->strings[i]=strdup(old->strings[i]);
   46.47 +    vector->strings[i]=NULL;
   46.48 +    return vector;
   46.49 +}
   46.50 +
   46.51 +void plover_vector_append(struct plover_vector *vector,const char *str)
   46.52 +{
   46.53 +    if (++(vector->len)>=vector->alloc)
   46.54 +    {
   46.55 +	vector->alloc*=2;
   46.56 +	vector->strings=realloc(vector->strings,vector->alloc*sizeof(char *));
   46.57 +    }
   46.58 +    vector->strings[vector->len-1]=strdup(str);
   46.59 +    vector->strings[vector->len]=NULL;
   46.60 +}
   46.61 +
   46.62 +int plover_vector_contains(struct plover_vector *vector,const char *str)
   46.63 +{
   46.64 +    int i;
   46.65 +    for(i=0;i<vector->len;i++)
   46.66 +	if (!strcmp(vector->strings[i],str))
   46.67 +	    return 1;
   46.68 +    return 0;
   46.69 +}
   46.70 +
   46.71 +int plover_vector_remove(struct plover_vector *vector,const char *str)
   46.72 +{
   46.73 +    int i;
   46.74 +    for(i=0;i<vector->len;i++)
   46.75 +	if (!strcmp(vector->strings[i],str))
   46.76 +	{
   46.77 +	    free(vector->strings[i]);
   46.78 +	    vector->len--;
   46.79 +	    vector->strings[i]=vector->strings[vector->len];
   46.80 +	    vector->strings[vector->len]=NULL;
   46.81 +	    return 1;
   46.82 +	}
   46.83 +    return 0;
   46.84 +}
   46.85 +
   46.86 +static int string_compar(const void *p1,const void *p2)
   46.87 +{
   46.88 +    return strcmp(*(char * const *)p1,*(char * const *)p2);
   46.89 +}
   46.90 +
   46.91 +void plover_vector_sort(struct plover_vector *vector)
   46.92 +{
   46.93 +    qsort(vector->strings,vector->len,sizeof(char *),string_compar);
   46.94 +}
   46.95 +
   46.96 +char *plover_vector_format_for_display(struct plover_vector *vector)
   46.97 +{
   46.98 +    int i,len;
   46.99 +    char *s,*p;
  46.100 +    if (!vector->len)
  46.101 +	return strdup("none");
  46.102 +    else if (vector->len==1)
  46.103 +	return strdup(vector->strings[0]);
  46.104 +    else
  46.105 +    {
  46.106 +	len=(vector->len-1)*2+5+1;
  46.107 +	for(i=0;i<vector->len;i++)
  46.108 +	    len+=strlen(vector->strings[i]);
  46.109 +	s=malloc(len);
  46.110 +	strcpy(s,vector->strings[0]);
  46.111 +	p=s+strlen(s);
  46.112 +	for(i=1;i<vector->len-1;i++)
  46.113 +	{
  46.114 +	    *p++=',';
  46.115 +	    *p++=' ';
  46.116 +	    strcpy(p,vector->strings[i]);
  46.117 +	    p+=strlen(p);
  46.118 +	}
  46.119 +	strcpy(p," and ");
  46.120 +	p+=5;
  46.121 +	strcpy(p,vector->strings[i]);
  46.122 +	return s;
  46.123 +    }
  46.124 +}
  46.125 +
  46.126 +void plover_vector_free(struct plover_vector *vector)
  46.127 +{
  46.128 +    int i;
  46.129 +    for(i=0;i<vector->len;i++)
  46.130 +	free(vector->strings[i]);
  46.131 +    free(vector->strings);
  46.132 +    free(vector);
  46.133 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/pre-inst/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
    47.3 @@ -0,0 +1,32 @@
    47.4 +AM_CFLAGS=-g $(SETUP_CFLAGS)
    47.5 +LDADD=../plover/libplover.la $(SETUP_LIBS)
    47.6 +if PLOVER_MINGW
    47.7 +LDADD+=-lcomctl32
    47.8 +# pre-inst is not intended to produce any output (and any that is produced
    47.9 +# can be safely junked). Thus -mwindows is appropriate since if called with
   47.10 +# a console window attached no output should be visible anyway and if called
   47.11 +# when no console window is attached we don't want one to be created.
   47.12 +AM_LDFLAGS=-mwindows
   47.13 +endif
   47.14 +INCLUDES=-I$(top_srcdir) -I$(srcdir)
   47.15 +
   47.16 +bin_PROGRAMS=pre-inst
   47.17 +
   47.18 +pre_inst_SOURCES=pre-inst.c
   47.19 +pre_inst_LDFLAGS=$(AM_LDFLAGS) -all-static
   47.20 +if HAVE_WINDRES
   47.21 +pre_inst_SOURCES+=resources.rc pre-inst.exe.manifest resource.h
   47.22 +endif
   47.23 +
   47.24 +.rc.$(OBJEXT):
   47.25 +	$(AM_V_GEN)$(WINDRES) $(INCLUDES) $< $@
   47.26 +
   47.27 +resources.$(OBJEXT): resources.rc resource.h pre-inst.exe.manifest pre-inst.ico
   47.28 +
   47.29 +.png.pnm:
   47.30 +	$(AM_V_GEN)pngtopnm $< | pnmquant -quiet 256 > $@
   47.31 +
   47.32 +pre-inst.ico:     icon16.pnm icon22.pnm icon32.pnm
   47.33 +	$(AM_V_GEN)ppmtowinicon -output=$@ $^
   47.34 +
   47.35 +EXTRA_DIST=icon16.png icon22.png icon32.png
    48.1 Binary file pre-inst/icon16.png has changed
    49.1 Binary file pre-inst/icon22.png has changed
    50.1 Binary file pre-inst/icon32.png has changed
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/pre-inst/manifest.xml.in	Sat Nov 15 19:04:45 2014 +0000
    51.3 @@ -0,0 +1,29 @@
    51.4 +changequote([,])dnl
    51.5 +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    51.6 +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    51.7 +  <assemblyIdentity
    51.8 +    version="@PLOVER_MAJOR_VERSION@.@PLOVER_MINOR_VERSION@.@PLOVER_MICRO_VERSION@.0"
    51.9 +    name="The plover development team.plover.pre-inst" type="win32"
   51.10 +    processorArchitecture="ifelse([@HOST_CPU@],[x86_64],[ia64],[x86])" />
   51.11 +  <description>Plover pre-inst program</description>
   51.12 +  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
   51.13 +    <application>
   51.14 +      <!-- Windows 7 functionality -->
   51.15 +      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
   51.16 +    </application>
   51.17 +  </compatibility>
   51.18 +  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
   51.19 +    <security>
   51.20 +      <requestedPrivileges>
   51.21 +        <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
   51.22 +      </requestedPrivileges>
   51.23 +    </security>
   51.24 +  </trustInfo>
   51.25 +  <dependency>
   51.26 +    <dependentAssembly>
   51.27 +      <assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls"
   51.28 +        version="6.0.0.0" processorArchitecture="*"
   51.29 +	publicKeyToken="6595b64144ccf1df" language="*"/>
   51.30 +    </dependentAssembly>
   51.31 +  </dependency>
   51.32 +</assembly>
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/pre-inst/pre-inst.c	Sat Nov 15 19:04:45 2014 +0000
    52.3 @@ -0,0 +1,504 @@
    52.4 +/*
    52.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
    52.6 + *
    52.7 + * This program is free software; you can redistribute it and/or modify
    52.8 + * it under the terms of the GNU General Public License as published by
    52.9 + * the Free Software Foundation; either version 2 of the License, or
   52.10 + * (at your option) any later version.
   52.11 + *
   52.12 + * This program is distributed in the hope that it will be useful,
   52.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.15 + * GNU General Public License for more details.
   52.16 + *
   52.17 + * You should have received a copy of the GNU General Public License along
   52.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
   52.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   52.20 + *
   52.21 + * References:
   52.22 + *	http://www.transmissionzero.co.uk/computing/win32-apps-with-mingw/
   52.23 + */
   52.24 +
   52.25 +#include "config.h"
   52.26 +#ifndef WIN32
   52.27 +#define _XOPEN_SOURCE 500
   52.28 +#endif
   52.29 +#include <stdlib.h>
   52.30 +#include <stdio.h>
   52.31 +#include <string.h>
   52.32 +#include <lua.h>
   52.33 +#include <razor.h>
   52.34 +#include <plover/plover.h>
   52.35 +#include <whelk/whelk.h>
   52.36 +#ifdef WIN32
   52.37 +#include <windows.h>
   52.38 +#include <process.h>
   52.39 +#include <commctrl.h>
   52.40 +#include "resource.h"
   52.41 +
   52.42 +#ifndef FOF_NO_UI
   52.43 +#define FOF_NO_UI	(FOF_SILENT|FOF_NOCONFIRMATION|FOF_NOERRORUI|\
   52.44 +			FOF_NOCONFIRMMKDIR)
   52.45 +#endif
   52.46 +
   52.47 +#else	/* WIN32 */
   52.48 +#include <ftw.h>
   52.49 +#endif	/* WIN32 */
   52.50 +
   52.51 +#ifdef WIN32
   52.52 +/* Under WIN32, g_spawn requires a helper program which we'd rather avoid */
   52.53 +#undef USE_G_SPAWN
   52.54 +#else
   52.55 +#define USE_G_SPAWN
   52.56 +#endif
   52.57 +
   52.58 +LUALIB_API int luaopen_posix(lua_State *L);
   52.59 +
   52.60 +#ifdef WIN32
   52.61 +DWORD main_thread_id;
   52.62 +#endif
   52.63 +
   52.64 +gchar *prefix;
   52.65 +
   52.66 +int verify_and_fix(const char *root)
   52.67 +{
   52.68 +    return 0;
   52.69 +}
   52.70 +
   52.71 +#ifdef WIN32
   52.72 +INT_PTR CALLBACK ProgressDialogProc(HWND dialog,UINT msg,WPARAM w_param,
   52.73 +  LPARAM l_param)
   52.74 +{
   52.75 +    HWND progress;
   52.76 +    DWORD style;
   52.77 +    switch (msg)
   52.78 +    {
   52.79 +	case WM_INITDIALOG:
   52.80 +	    progress=GetDlgItem(dialog,IDC_PROGRESS); 
   52.81 +	    style=GetWindowLong(progress,GWL_STYLE);
   52.82 +	    SetWindowLong(progress,GWL_STYLE,style|PBS_MARQUEE);
   52.83 +	    SendMessage(progress,PBM_SETMARQUEE,(WPARAM)TRUE,(LPARAM)30);
   52.84 +	    return (INT_PTR)TRUE;
   52.85 +    }
   52.86 +    return (INT_PTR)FALSE;
   52.87 +}
   52.88 +#endif
   52.89 +
   52.90 +#ifdef WIN32
   52.91 +__stdcall
   52.92 +#endif
   52.93 +unsigned pre_install_thread(void *data)
   52.94 +{
   52.95 +    int retval;
   52.96 +    char *path=data;
   52.97 +    gchar *s;
   52.98 +    char *install[]={"plover-gtkui",NULL};
   52.99 +    GError *error=NULL;
  52.100 +    prefix=plover_pre_install_prefix();
  52.101 +    s=g_strconcat(prefix,"/var/log/pre-install",NULL);
  52.102 +    plover_log_open(s);
  52.103 +    g_free(s);
  52.104 +    s=g_strconcat(prefix,"/var/lib/razor",NULL);
  52.105 +    razor_set_database_path(s);
  52.106 +    g_free(s);
  52.107 +    if (verify_and_fix(prefix))
  52.108 +    {
  52.109 +	free(path);
  52.110 +	g_free(prefix);
  52.111 +	return -1;
  52.112 +    }
  52.113 +    retval=!plover_install(path,prefix,install,&error);
  52.114 +    if (!retval)
  52.115 +	retval=!plover_update(path,prefix,NULL,&error);
  52.116 +    if (error)
  52.117 +    {
  52.118 +	fprintf(stderr,"%s\n",error->message);
  52.119 +	g_error_free(error);
  52.120 +    }
  52.121 +    free(path);
  52.122 +#ifdef WIN32
  52.123 +    PostQuitMessage(retval);
  52.124 +    PostThreadMessage(main_thread_id,WM_QUIT,retval,0);
  52.125 +    _endthreadex(retval);
  52.126 +#endif
  52.127 +    return retval;
  52.128 +}
  52.129 +
  52.130 +/*
  52.131 + * The idea is that if pre_install() fails, update/setup should fall back
  52.132 + * to console interfaces.
  52.133 + */
  52.134 +#ifdef WIN32
  52.135 +HANDLE
  52.136 +#else
  52.137 +void *
  52.138 +#endif
  52.139 +pre_install(const char *argv0)
  52.140 +{
  52.141 +#ifdef WIN32
  52.142 +    HANDLE retval;
  52.143 +#else
  52.144 +    void *retval;
  52.145 +#endif
  52.146 +    char *path;
  52.147 +    razor_set_lua_loader("posix",luaopen_posix);
  52.148 +    razor_set_lua_loader("whelk",luaopen_whelk);
  52.149 +    path=plover_get_program_directory(argv0);
  52.150 +#ifdef WIN32
  52.151 +    retval=(HANDLE)_beginthreadex(NULL,0,pre_install_thread,path,0,NULL);
  52.152 +#else
  52.153 +    if (pre_install_thread(path))
  52.154 +	retval=NULL;
  52.155 +    else
  52.156 +	retval=(void *)1;		/* Non-NULL to indicate success */
  52.157 +#endif
  52.158 +    return retval;
  52.159 +}
  52.160 +
  52.161 +#ifndef WIN32
  52.162 +int remove_ignore(const char *fpath,const struct stat *sb,int typeflag,
  52.163 +  struct FTW *ftwbuf)
  52.164 +{
  52.165 +    (void)remove(fpath);
  52.166 +    return 0;
  52.167 +}
  52.168 +#endif
  52.169 +
  52.170 +gboolean deltree(const char *path)
  52.171 +{
  52.172 +#ifdef WIN32
  52.173 +    /* Based on g_local_file_trash() */
  52.174 +    SHFILEOPSTRUCTW op={0};
  52.175 +    gboolean success;
  52.176 +    wchar_t *wfilename;
  52.177 +    long len;
  52.178 +    wfilename=g_utf8_to_utf16(path,-1,NULL,&len,NULL);
  52.179 +    /* SHFILEOPSTRUCT.pFrom is double-zero-terminated */
  52.180 +    wfilename=g_renew(wchar_t,wfilename,len+2);
  52.181 +    wfilename[len+1]=0;
  52.182 +    op.wFunc=FO_DELETE;
  52.183 +    op.pFrom=wfilename;
  52.184 +    op.fFlags=FOF_NO_UI;
  52.185 +    success=!SHFileOperationW(&op);
  52.186 +    if (success && op.fAnyOperationsAborted)
  52.187 +	success=FALSE;
  52.188 +    g_free(wfilename);
  52.189 +    return success;
  52.190 +#else
  52.191 +    return nftw(path,remove_ignore,64,FTW_DEPTH|FTW_PHYS);
  52.192 +#endif
  52.193 +}
  52.194 +
  52.195 +gboolean pre_uninstall(void)
  52.196 +{
  52.197 +    gboolean success;
  52.198 +    gchar *s;
  52.199 +    GError *error=NULL;
  52.200 +    razor_set_lua_loader("posix",luaopen_posix);
  52.201 +    razor_set_lua_loader("whelk",luaopen_whelk);
  52.202 +    prefix=plover_pre_install_prefix();
  52.203 +    s=g_strconcat(prefix,"/var/lib/razor",NULL);
  52.204 +    razor_set_database_path(s);
  52.205 +    g_free(s);
  52.206 +    success=plover_remove(NULL,&error);
  52.207 +    if (error)
  52.208 +    {
  52.209 +	fprintf(stderr,"%s\n",error->message);
  52.210 +	g_error_free(error);
  52.211 +    }
  52.212 +    deltree(prefix);
  52.213 +    return success;
  52.214 +}
  52.215 +
  52.216 +#if defined(WIN32) && !defined(USE_G_SPAWN)
  52.217 +/* Based on glib's g_spawn_win32.c */
  52.218 +
  52.219 +static gchar *
  52.220 +win32_cmdline_quote(const char *string)
  52.221 +{
  52.222 +    const gchar *p=string;
  52.223 +    gchar *retval,*q;
  52.224 +    gint len=0;
  52.225 +    gboolean need_dblquotes=FALSE;
  52.226 +    while (*p)
  52.227 +    {
  52.228 +	if (*p==' ' || *p=='\t')
  52.229 +	    need_dblquotes=TRUE;
  52.230 +	else if (*p=='"')
  52.231 +	    len++;
  52.232 +	else if (*p=='\\')
  52.233 +	{
  52.234 +	    const gchar *pp=p;
  52.235 +	    while (*pp && *pp=='\\')
  52.236 +		pp++;
  52.237 +	    if (*pp=='"')
  52.238 +		len++;
  52.239 +	}
  52.240 +	len++;
  52.241 +	p++;
  52.242 +    }
  52.243 +    q=retval=g_malloc(len+need_dblquotes*2+1);
  52.244 +    p=string;
  52.245 +    if (need_dblquotes)
  52.246 +	*q++='"';
  52.247 +    while (*p)
  52.248 +    {
  52.249 +	if (*p=='"')
  52.250 +	    *q++='\\';
  52.251 +	else if (*p=='\\')
  52.252 +	{
  52.253 +	    const gchar *pp=p;
  52.254 +	    while (*pp && *pp=='\\')
  52.255 +		pp++;
  52.256 +	    if (*pp=='"')
  52.257 +		*q++='\\';
  52.258 +	}
  52.259 +	*q++=*p;
  52.260 +	p++;
  52.261 +    }
  52.262 +    if (need_dblquotes)
  52.263 +	*q++='"';
  52.264 +    *q++='\0';
  52.265 +    return retval;
  52.266 +}
  52.267 +
  52.268 +/* Create a win32-style wide-character argv with suitable quoting */
  52.269 +wchar_t **win32_argv_import(char **argv,GError **error)
  52.270 +{
  52.271 +    int i,n;
  52.272 +    gchar *s;
  52.273 +    wchar_t **wargv;
  52.274 +    GError *tmp_error=NULL;
  52.275 +    n=g_strv_length(argv);
  52.276 +    wargv=g_new(wchar_t *,n+1);
  52.277 +    for(i=0;i<n;i++)
  52.278 +    {
  52.279 +	s=win32_cmdline_quote(argv[i]);
  52.280 +	wargv[i]=g_utf8_to_utf16(s,-1,NULL,NULL,&tmp_error);
  52.281 +	g_free(s);
  52.282 +	if (!wargv[i])
  52.283 +	{
  52.284 +	    g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
  52.285 +	      "Invalid argument #%d: %s",i,tmp_error->message);
  52.286 +	    g_error_free(tmp_error);
  52.287 +	    for(i--;i>=0;i--)
  52.288 +		g_free(wargv[i]);
  52.289 +	    g_free(wargv);
  52.290 +	    return FALSE;
  52.291 +	}
  52.292 +    }
  52.293 +    wargv[i]=NULL;
  52.294 +    return wargv;
  52.295 +}
  52.296 +
  52.297 +gboolean spawn_sync(char **argv,GError **error)
  52.298 +{
  52.299 +    wchar_t *wargv0,**wargv;
  52.300 +    gintptr rc;
  52.301 +    GError *tmp_error=NULL;
  52.302 +    wargv0=g_utf8_to_utf16(argv[0],-1,NULL,NULL,&tmp_error);
  52.303 +    if (!wargv0)
  52.304 +    {
  52.305 +	fprintf(stderr,"Conversion error in post\n");
  52.306 +	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
  52.307 +	  "Invalid program name: %s",tmp_error->message);
  52.308 +	g_error_free(tmp_error);
  52.309 +	return FALSE;
  52.310 +    }
  52.311 +    wargv=win32_argv_import(argv,error);
  52.312 +    if (!wargv)
  52.313 +    {
  52.314 +	fprintf(stderr,"Conversion error in post\n");
  52.315 +	g_free(wargv0);
  52.316 +	return FALSE;
  52.317 +    }
  52.318 +    errno=0;
  52.319 +    rc=_wspawnvp(P_WAIT,wargv0,(const wchar_t **)wargv);
  52.320 +    g_free(wargv0);
  52.321 +    g_strfreev((gchar **)wargv);
  52.322 +    if (rc==-1 && errno!=0)
  52.323 +    {
  52.324 +	fprintf(stderr,"Failed to start post command (%s)\n",g_strerror(errno));
  52.325 +	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
  52.326 +	  "Failed to execute post command: %s",g_strerror(errno));
  52.327 +	return FALSE;
  52.328 +    }
  52.329 +    if (rc!=EXIT_SUCCESS)
  52.330 +    {
  52.331 +	fprintf(stderr,"post command failed (%ld)\n",(long)rc);
  52.332 +	g_set_error(error,G_SPAWN_ERROR,G_SPAWN_ERROR_FAILED,
  52.333 +	  "Post command exited with code %ld",(long)rc);
  52.334 +	return FALSE;
  52.335 +    }
  52.336 +    return TRUE;
  52.337 +}
  52.338 +
  52.339 +#endif /* defined(WIN32) && !defined(USE_G_SPAWN) */
  52.340 +
  52.341 +/*
  52.342 + * Run a command after completing request.
  52.343 + *
  52.344 + * Command may refer to %INSTALL_PREFIX% which will be replaced by the
  52.345 + * (first) install prefix used and/or %TEST_RESULT% which will be replaced
  52.346 + * bu either "pass" or "fail" depending as to whether the request succeeded
  52.347 + * or not. Command may also include double quotes which will be used to
  52.348 + * affect how the command is split into arguments much like a shell does.
  52.349 + */
  52.350 +gboolean run_post(int argc,char **argv,gboolean test_result,GError **error)
  52.351 +{
  52.352 +    int i,post_argc;
  52.353 +    char *s;
  52.354 +    gchar *expanded;
  52.355 +    gchar **post_argv;
  52.356 +#ifdef USE_G_SPAWN
  52.357 +    gchar *standard_output,*standard_error;
  52.358 +    int exit_status;
  52.359 +#endif
  52.360 +    GError *tmp_error=NULL;
  52.361 +    if (argc<1)
  52.362 +    {
  52.363 +	g_set_error_literal(error,G_FILE_ERROR,G_FILE_ERROR_NOENT,
  52.364 +	  "--post: No command given");
  52.365 +	return FALSE;
  52.366 +    }
  52.367 +    printf("Running post command: %s\n",argv[1]);
  52.368 +    if (!g_shell_parse_argv(argv[1],&post_argc,&post_argv,&tmp_error))
  52.369 +    {
  52.370 +	g_propagate_prefixed_error(error,tmp_error,"%s: ",argv[1]);
  52.371 +	return FALSE;
  52.372 +    }
  52.373 +    for(i=0;i<post_argc;i++)
  52.374 +    {
  52.375 +	s=strstr(post_argv[i],"%INSTALL_PREFIX%");
  52.376 +	if (s)
  52.377 +	{
  52.378 +	    *s='\0';
  52.379 +	    s+=strlen("%INSTALL_PREFIX%");
  52.380 +	    expanded=g_strconcat(post_argv[i],prefix,s,NULL);
  52.381 +	    g_free(post_argv[i]);
  52.382 +	    post_argv[i]=expanded;
  52.383 +	}
  52.384 +	s=strstr(post_argv[i],"%TEST_RESULT%");
  52.385 +	if (s)
  52.386 +	{
  52.387 +	    *s='\0';
  52.388 +	    s+=strlen("%TEST_RESULT%");
  52.389 +	    expanded=g_strconcat(post_argv[i],test_result?"pass":"fail",s,NULL);
  52.390 +	    g_free(post_argv[i]);
  52.391 +	    post_argv[i]=expanded;
  52.392 +	}
  52.393 +    }
  52.394 +#ifdef USE_G_SPAWN
  52.395 +    if (!g_spawn_sync(NULL,post_argv,NULL,G_SPAWN_SEARCH_PATH,NULL,NULL,
  52.396 +      &standard_output,&standard_error,&exit_status,&tmp_error))
  52.397 +    {
  52.398 +	fprintf(stderr,"Failed to start post command\n");
  52.399 +	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
  52.400 +	return FALSE;
  52.401 +    }
  52.402 +    if (standard_output && *standard_output)
  52.403 +    {
  52.404 +	printf("Output from post command %s:\n",post_argv[0]);
  52.405 +	fputs(standard_output,stdout);
  52.406 +    }
  52.407 +    g_free(standard_output);
  52.408 +    if (standard_error && *standard_error)
  52.409 +    {
  52.410 +	printf("Error output from post command %s:\n",post_argv[0]);
  52.411 +	fputs(standard_error,stdout);
  52.412 +    }
  52.413 +    g_free(standard_error);
  52.414 +    if (!g_spawn_check_exit_status(exit_status,&tmp_error))
  52.415 +    {
  52.416 +	fprintf(stderr,"post command failed\n");
  52.417 +	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
  52.418 +	return FALSE;
  52.419 +    }
  52.420 +#else
  52.421 +    if (!spawn_sync(post_argv,&tmp_error))
  52.422 +    {
  52.423 +	g_propagate_prefixed_error(error,tmp_error,"%s: ",post_argv[0]);
  52.424 +	return FALSE;
  52.425 +    }
  52.426 +#endif
  52.427 +    return TRUE;
  52.428 +}
  52.429 +
  52.430 +#ifdef WIN32
  52.431 +DWORD win32_pre_install_gui(char *argv0)
  52.432 +{
  52.433 +    HANDLE thread;
  52.434 +    INITCOMMONCONTROLSEX icc={0,};
  52.435 +    MSG msg;
  52.436 +    DWORD retval;
  52.437 +    main_thread_id=GetCurrentThreadId();
  52.438 +    thread=(HANDLE)pre_install(argv0);
  52.439 +    if (!thread)
  52.440 +	return EXIT_FAILURE;
  52.441 +    icc.dwSize=sizeof(icc);
  52.442 +    icc.dwICC=ICC_WIN95_CLASSES;
  52.443 +    InitCommonControlsEx(&icc);
  52.444 +    DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PROGRESSDIALOG),NULL,
  52.445 +      &ProgressDialogProc);
  52.446 +    while(GetMessage(&msg,NULL,0,0)>0)
  52.447 +    {
  52.448 +	TranslateMessage(&msg);
  52.449 +	DispatchMessage(&msg);
  52.450 +    }
  52.451 +    WaitForSingleObject(thread,INFINITE);
  52.452 +    GetExitCodeThread(thread,&retval);
  52.453 +    CloseHandle(thread);
  52.454 +    return retval;
  52.455 +}
  52.456 +#endif	/* WIN32 */
  52.457 +
  52.458 +int main(int argc,char **argv)
  52.459 +{
  52.460 +    gboolean success;
  52.461 +    GError *error=NULL;
  52.462 +#ifdef WIN32
  52.463 +    /*
  52.464 +     * pre-inst is normally a GUI application, but rpm scripts may well
  52.465 +     * call console applications and it looks ugly if console windows keep
  52.466 +     * popping up. Avoid this by allocating our own console and hiding it.
  52.467 +     * Note:
  52.468 +     *	- If pre-inst is a console application (typically for debugging),
  52.469 +     *    then skip this step.
  52.470 +     *  - Call ShowWindow twice to negate special handling on first call.
  52.471 +     */
  52.472 +    if (!GetConsoleWindow())
  52.473 +    {
  52.474 +	AllocConsole();
  52.475 +	ShowWindow(GetConsoleWindow(),SW_HIDE);
  52.476 +	ShowWindow(GetConsoleWindow(),SW_HIDE);
  52.477 +    }
  52.478 +#endif
  52.479 +    if (argc>1 && !strcmp(argv[1],"-u"))
  52.480 +    {
  52.481 +	success=pre_uninstall();
  52.482 +	argc--;
  52.483 +	argv++;
  52.484 +    }
  52.485 +    else
  52.486 +#ifdef WIN32
  52.487 +	success=win32_pre_install_gui(argv[0])==EXIT_SUCCESS;
  52.488 +#else
  52.489 +	success=!!pre_install(argv[0]);
  52.490 +#endif
  52.491 +    if (argc>1 && !strcmp(argv[1],"--post") &&
  52.492 +      !run_post(argc-1,argv+1,success,&error))
  52.493 +    {
  52.494 +#ifndef WIN32
  52.495 +	fprintf(stderr,"Error in post: %s\n",error->message);
  52.496 +#else
  52.497 +	MessageBox(NULL,error->message,"Error in post",MB_ICONERROR|MB_OK);
  52.498 +#endif
  52.499 +	g_error_free(error);
  52.500 +	success=FALSE;
  52.501 +    }
  52.502 +#ifdef WIN32
  52.503 +    return success?EXIT_SUCCESS:EXIT_FAILURE;
  52.504 +#else
  52.505 +    return success?0:1;
  52.506 +#endif
  52.507 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/pre-inst/resource.h	Sat Nov 15 19:04:45 2014 +0000
    53.3 @@ -0,0 +1,6 @@
    53.4 +#define IDD_PROGRESSDIALOG		100
    53.5 +#define IDC_PROGRESS			1000
    53.6 +
    53.7 +#ifndef IDC_STATIC
    53.8 +#define IDC_STATIC			-1
    53.9 +#endif
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/pre-inst/resources.rc.in	Sat Nov 15 19:04:45 2014 +0000
    54.3 @@ -0,0 +1,47 @@
    54.4 +#include <windows.h>
    54.5 +#include "resource.h"
    54.6 +
    54.7 +#pragma code_page(65001)
    54.8 +
    54.9 +MAINICON ICON "pre-inst.ico"
   54.10 +
   54.11 +VS_VERSION_INFO VERSIONINFO
   54.12 +    FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   54.13 +      @PLOVER_MICRO_VERSION@,0
   54.14 +    PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,
   54.15 +      @PLOVER_MICRO_VERSION@,0
   54.16 +    FILEOS VOS__WINDOWS32
   54.17 +    FILETYPE VFT_APP
   54.18 +    {
   54.19 +	BLOCK "StringFileInfo"
   54.20 +	{
   54.21 +	    BLOCK "080904B0"
   54.22 +	    {
   54.23 +		VALUE "CompanyName","The plover development team"
   54.24 +		VALUE "FileDescription","Plover pre-inst program"
   54.25 +		VALUE "FileVersion","@PACKAGE_VERSION@"
   54.26 +		VALUE "InternalName","pre-inst"
   54.27 +		VALUE "LegalCopyright",
   54.28 +		  "Copyright © 2014 J. Ali Harlow et al"
   54.29 +		VALUE "OriginalFilename","pre-inst.exe"
   54.30 +		VALUE "ProductName","plover"
   54.31 +		VALUE "ProductVersion","@PACKAGE_VERSION@"
   54.32 +	    }
   54.33 +	}
   54.34 +	BLOCK "VarFileInfo"
   54.35 +	{
   54.36 +	    VALUE "Translation",0x809,0x4B0
   54.37 +	}
   54.38 +    }
   54.39 +
   54.40 +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "pre-inst.exe.manifest"
   54.41 +
   54.42 +IDD_PROGRESSDIALOG DIALOGEX 0,0,167,67
   54.43 +    STYLE DS_SETFONT|DS_MODALFRAME|DS_FIXEDSYS|WS_POPUP|WS_CAPTION
   54.44 +    CAPTION "Preparing to install..."
   54.45 +    FONT 8,"MS Shell Dlg",400,0,0x1
   54.46 +    {
   54.47 +	ICON MAINICON,IDC_STATIC,10,17,20,20
   54.48 +	LTEXT "Unpacking installation program.",IDC_STATIC,45,16,106,8
   54.49 +	CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,45,28,106,8
   54.50 +    }
    55.1 --- a/setup/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
    55.2 +++ b/setup/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
    55.3 @@ -3,6 +3,7 @@
    55.4  INCLUDES=-I$(top_srcdir)
    55.5  
    55.6  bin_PROGRAMS=setup
    55.7 +bin_SCRIPTS=setup.js
    55.8  
    55.9  setup_SOURCES=setup.c
   55.10  setup_LDFLAGS=-all-static
   55.11 @@ -10,13 +11,19 @@
   55.12  setup_SOURCES+=resources.rc setup.exe.manifest
   55.13  endif
   55.14  
   55.15 -.png.pnm:
   55.16 -	pngtopnm $< | pnmquant 256 > $@
   55.17 +.rc.$(OBJEXT):
   55.18 +	$(AM_V_GEN)$(WINDRES) resources.rc $@
   55.19  
   55.20  resources.$(OBJEXT): resources.rc setup.exe.manifest setup.ico
   55.21 -	$(WINDRES) resources.rc $@
   55.22 +
   55.23 +%.js: $(srcdir)/%.js.in
   55.24 +	$(AM_V_GEN)sed -e 's/$$/\r/' $(srcdir)/$@.in > $@
   55.25 +
   55.26 +.png.pnm:
   55.27 +	$(AM_V_GEN)pngtopnm $< | pnmquant -quiet 256 > $@
   55.28  
   55.29  setup.ico:     icon16.pnm icon22.pnm icon32.pnm
   55.30 -	ppmtowinicon -output=$@ $^
   55.31 +	$(AM_V_GEN)ppmtowinicon -output=$@ $^
   55.32  
   55.33 -EXTRA_DIST=icon16.png icon22.png icon32.png
   55.34 +EXTRA_DIST=icon16.png icon22.png icon32.png setup.js.in
   55.35 +CLEANFILES=setup.js
    56.1 --- a/setup/resources.rc.in	Fri Mar 23 20:29:50 2012 +0000
    56.2 +++ b/setup/resources.rc.in	Sat Nov 15 19:04:45 2014 +0000
    56.3 @@ -1,6 +1,8 @@
    56.4  #include <winver.h>
    56.5  #include <winuser.h>
    56.6  
    56.7 +#pragma code_page(65001)
    56.8 +
    56.9  MAINICON ICON "setup.ico"
   56.10  
   56.11  VS_VERSION_INFO VERSIONINFO
   56.12 @@ -20,7 +22,7 @@
   56.13  		VALUE "FileVersion","@PACKAGE_VERSION@"
   56.14  		VALUE "InternalName","setup"
   56.15  		VALUE "LegalCopyright",
   56.16 -		  "Copyright (c) 2009,2011,2012 J. Ali Harlow et al"
   56.17 +		  "Copyright © 2009,2011,2012 J. Ali Harlow et al"
   56.18  		VALUE "OriginalFilename","setup.exe"
   56.19  		VALUE "ProductName","plover"
   56.20  		VALUE "ProductVersion","@PACKAGE_VERSION@"
    57.1 --- a/setup/setup.c	Fri Mar 23 20:29:50 2012 +0000
    57.2 +++ b/setup/setup.c	Sat Nov 15 19:04:45 2014 +0000
    57.3 @@ -31,67 +31,25 @@
    57.4  
    57.5  LUALIB_API int luaopen_posix(lua_State *L);
    57.6  
    57.7 -struct vector {
    57.8 -    int len,alloc;
    57.9 -    char **strings;
   57.10 -};
   57.11 -
   57.12 -struct vector *vector_new(void)
   57.13 -{
   57.14 -    struct vector *vector;
   57.15 -    vector=malloc(sizeof(*vector));
   57.16 -    vector->len=0;
   57.17 -    vector->alloc=16;
   57.18 -    vector->strings=calloc(vector->alloc,sizeof(char *));
   57.19 -    return vector;
   57.20 -}
   57.21 -
   57.22 -void vector_append(struct vector *vector,const char *str)
   57.23 -{
   57.24 -    if (++(vector->len)>=vector->alloc)
   57.25 -    {
   57.26 -	vector->alloc*=2;
   57.27 -	vector->strings=realloc(vector->strings,vector->alloc*sizeof(char *));
   57.28 -    }
   57.29 -    vector->strings[vector->len-1]=strdup(str);
   57.30 -    vector->strings[vector->len]=NULL;
   57.31 -}
   57.32 -
   57.33 -int vector_contains(struct vector *vector,const char *str)
   57.34 -{
   57.35 -    int i;
   57.36 -    for(i=0;i<vector->len;i++)
   57.37 -	if (!strcmp(vector->strings[i],str))
   57.38 -	    return 1;
   57.39 -    return 0;
   57.40 -}
   57.41 -
   57.42 -void vector_free(struct vector *vector)
   57.43 -{
   57.44 -    int i;
   57.45 -    for(i=0;i<vector->len;i++)
   57.46 -	free(vector->strings[i]);
   57.47 -    free(vector->strings);
   57.48 -    free(vector);
   57.49 -}
   57.50 -
   57.51  void setup(const char *argv0)
   57.52  {
   57.53 -    char *path,*s,*prefix;
   57.54 +    char *path;
   57.55 +    gchar *s,*prefix;
   57.56      int ch,changed;
   57.57      struct comps *comps;
   57.58      struct comps_group *group;
   57.59      struct comps_requirement *pkg;
   57.60 -    struct vector *packages=NULL;
   57.61 +    struct plover_vector *packages=NULL;
   57.62 +    GError *error=NULL;
   57.63      path=plover_get_program_directory(argv0);
   57.64 -    s=plover_strconcat(path,"/repodata/comps.xml",NULL);
   57.65 +    s=g_strconcat(path,"/repodata/comps.xml",NULL);
   57.66      comps=plover_comps_new_from_file(s);
   57.67      if (!comps)
   57.68      {
   57.69  	perror(s);
   57.70  	exit(1);
   57.71      }
   57.72 -    free(s);
   57.73 +    g_free(s);
   57.74      prefix=plover_default_prefix_for_vendor(comps->vendor);
   57.75      if (!plover_installed_files_match_prefix(prefix))
   57.76      {
   57.77 @@ -103,7 +61,12 @@
   57.78  	    exit(1);
   57.79  	while(ch!='\n' && ch!=EOF)
   57.80  	    ch=getchar();
   57.81 -	plover_remove(NULL);
   57.82 +	if (plover_remove(NULL,&error))
   57.83 +	{
   57.84 +	    fprintf(stderr,"%s\n",error->message);
   57.85 +	    g_error_free(error);
   57.86 +	    exit(1);
   57.87 +	}
   57.88      }
   57.89      group=plover_comps_lookup_group(comps,"base");
   57.90      if (!group)
   57.91 @@ -111,21 +74,21 @@
   57.92  	fprintf(stderr,"No base group found in comps.xml\n");
   57.93  	exit(1);
   57.94      }
   57.95 -    packages=vector_new();
   57.96 +    packages=plover_vector_new();
   57.97      do
   57.98      {
   57.99  	changed=0;
  57.100  	for(pkg=group->packages;pkg;pkg=pkg->next)
  57.101  	{
  57.102 -	    if (vector_contains(packages,pkg->name))
  57.103 +	    if (plover_vector_contains(packages,pkg->name))
  57.104  		continue;
  57.105  	    if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
  57.106  	      pkg->type==COMPS_REQUIREMENT_MANDATORY ||
  57.107  	      pkg->type==COMPS_REQUIREMENT_CONDITIONAL &&
  57.108 -	      vector_contains(packages,pkg->requires))
  57.109 +	      plover_vector_contains(packages,pkg->requires))
  57.110  	    {
  57.111  		changed++;
  57.112 -		vector_append(packages,pkg->name);
  57.113 +		plover_vector_append(packages,pkg->name);
  57.114  	    }
  57.115  	}
  57.116      } while(changed);
  57.117 @@ -135,18 +98,31 @@
  57.118  	fprintf(stderr,"No packages to install\n");
  57.119  	exit(1);
  57.120      }
  57.121 -    plover_install(path,prefix,packages->strings);
  57.122 -    vector_free(packages);
  57.123 -    free(prefix);
  57.124 +    if (!plover_install(path,prefix,packages->strings,&error))
  57.125 +    {
  57.126 +	fprintf(stderr,"%s\n",error->message);
  57.127 +	g_error_free(error);
  57.128 +	exit(1);
  57.129 +    }
  57.130 +    plover_vector_free(packages);
  57.131 +    g_free(prefix);
  57.132      free(path);
  57.133  }
  57.134  
  57.135  int main(int argc,char **argv)
  57.136  {
  57.137 +    GError *error=NULL;
  57.138      razor_set_lua_loader("posix",luaopen_posix);
  57.139      razor_set_lua_loader("whelk",luaopen_whelk);
  57.140      if (argc>1 && !strcmp(argv[1],"-u"))
  57.141 -	plover_remove(NULL);
  57.142 +    {
  57.143 +	if (!plover_remove(NULL,&error))
  57.144 +	{
  57.145 +	    fprintf(stderr,"%s\n",error->message);
  57.146 +	    g_error_free(error);
  57.147 +	    exit(1);
  57.148 +	}
  57.149 +    }
  57.150      else
  57.151  	setup(argv[0]);
  57.152      exit(0);
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/setup/setup.js.in	Sat Nov 15 19:04:45 2014 +0000
    58.3 @@ -0,0 +1,92 @@
    58.4 +var WshShell = WScript.CreateObject("WScript.Shell");
    58.5 +var ScriptPath = WScript.ScriptFullName.replace(/\\[^\\]*$/, "");
    58.6 +var FileSystemObject = new ActiveXObject("Scripting.FileSystemObject");
    58.7 +
    58.8 +function RunSetup(args)
    58.9 +{
   58.10 +    var OKButton = 0, ErrorIcon = 16, ForReading = 1;
   58.11 +    var path, command, i, ExecObject, text;
   58.12 +    path = FileSystemObject.BuildPath(ScriptPath, "setup.exe");
   58.13 +    command = "\"" + path + "\"";
   58.14 +    for(i = 0; i < args.Length; i++)
   58.15 +	command += " \"" + args.Item(i) + "\"";
   58.16 +    ExecObject = WshShell.Exec(command);
   58.17 +    if (!ExecObject.StdErr.AtEndOfStream)
   58.18 +    {
   58.19 +	text = "Setup failed for an unexpected reason. Please report "
   58.20 +	  + "the following error to support@city-occupational.co.uk:\n\n"
   58.21 +	  + ExecObject.StdErr.ReadAll();
   58.22 +	WshShell.Popup(text, 0, "Setup failed", OKButton + ErrorIcon);
   58.23 +	return false;
   58.24 +    }
   58.25 +    else if (ExecObject.ExitCode)
   58.26 +    {
   58.27 +	text = "Setup failed without giving a reason. Please report "
   58.28 +	  + "this to support@city-occupational.co.uk";
   58.29 +	WshShell.Popup(text, 0, "Setup failed", OKButton + ErrorIcon);
   58.30 +	return false;
   58.31 +    }
   58.32 +    return true;
   58.33 +}
   58.34 +
   58.35 +function Install()
   58.36 +{
   58.37 +    var path;
   58.38 +    path = FileSystemObject.BuildPath(ScriptPath, "pre-inst.exe");
   58.39 +    WshShell.Run("\"" + path + "\"" + " --post \"wscript.exe"
   58.40 +      + " \\\"" + WScript.ScriptFullName + "\\\""
   58.41 +      + " --post %INSTALL_PREFIX% %TEST_RESULT%\"",
   58.42 +      7, true);
   58.43 +}
   58.44 +
   58.45 +function Uninstall()
   58.46 +{
   58.47 +    var path;
   58.48 +    path = FileSystemObject.BuildPath(ScriptPath, "pre-inst.exe");
   58.49 +    WshShell.Run("\"" + path + "\"" + " -u --post \"wscript.exe"
   58.50 +      + " \\\"" + WScript.ScriptFullName + "\\\"" + " --postun\"", 7, true);
   58.51 +}
   58.52 +
   58.53 +function PostInstall()
   58.54 +{
   58.55 +    var OKButton = 0, InfoIcon = 64, text;
   58.56 +    var test_result, install_prefix, path, args;
   58.57 +    install_prefix = WScript.Arguments.Item(1);
   58.58 +    test_result = WScript.Arguments.Item(2);
   58.59 +    if (test_result == "pass")
   58.60 +    {
   58.61 +	path = FileSystemObject.BuildPath(install_prefix,
   58.62 +	  "bin\\app-manager.exe");
   58.63 +	WshShell.Run("\"" + path + "\" --setup \"" + ScriptPath + "\"");
   58.64 +    }
   58.65 +    else
   58.66 +    {
   58.67 +	args = { Length:0, Item:function(){return nil} };
   58.68 +	if (RunSetup(args))
   58.69 +	{
   58.70 +	    text = "Software installation completed successfully.";
   58.71 +	    WshShell.Popup(text, 0, "Software Installation",
   58.72 +	      OKButton + InfoIcon);
   58.73 +	}
   58.74 +    }
   58.75 +}
   58.76 +
   58.77 +function PostUninstall()
   58.78 +{
   58.79 +    var args = { Length:1, Item:function(){return "-u"} };
   58.80 +    var OKButton = 0, InfoIcon = 64, text;
   58.81 +    if (RunSetup(args))
   58.82 +    {
   58.83 +	text = "Uninstall completed successfully.";
   58.84 +	WshShell.Popup(text, 0, "Uninstall", OKButton + InfoIcon);
   58.85 +    }
   58.86 +}
   58.87 +
   58.88 +if (WScript.Arguments.Length < 1)
   58.89 +    Install()
   58.90 +else if (WScript.Arguments.Item(0) == "-u")
   58.91 +    Uninstall()
   58.92 +else if (WScript.Arguments.Length >= 3 && WScript.Arguments.Item(0) == "--post")
   58.93 +    PostInstall()
   58.94 +else if (WScript.Arguments.Item(0) == "--postun")
   58.95 +    PostUninstall()
    59.1 --- a/update/Makefile.am	Fri Mar 23 20:29:50 2012 +0000
    59.2 +++ b/update/Makefile.am	Sat Nov 15 19:04:45 2014 +0000
    59.3 @@ -3,6 +3,7 @@
    59.4  INCLUDES=-I$(top_srcdir)
    59.5  
    59.6  bin_PROGRAMS=update
    59.7 +bin_SCRIPTS=update.js
    59.8  
    59.9  update_SOURCES=update.c
   59.10  update_LDFLAGS=-all-static
   59.11 @@ -10,13 +11,19 @@
   59.12  update_SOURCES+=resources.rc update.exe.manifest
   59.13  endif
   59.14  
   59.15 -.png.pnm:
   59.16 -	pngtopnm $< | pnmquant 256 > $@
   59.17 +.rc.$(OBJEXT):
   59.18 +	$(AM_V_GEN)$(WINDRES) resources.rc $@
   59.19  
   59.20  resources.$(OBJEXT): resources.rc update.exe.manifest update.ico
   59.21 -	$(WINDRES) resources.rc $@
   59.22 +
   59.23 +%.js: $(srcdir)/%.js.in
   59.24 +	$(AM_V_GEN)sed -e 's/$$/\r/' $(srcdir)/$@.in > $@
   59.25 +
   59.26 +.png.pnm:
   59.27 +	$(AM_V_GEN)pngtopnm $< | pnmquant -quiet 256 > $@
   59.28  
   59.29  update.ico:     icon16.pnm icon22.pnm icon32.pnm
   59.30 -	ppmtowinicon -output=$@ $^
   59.31 +	$(AM_V_GEN)ppmtowinicon -output=$@ $^
   59.32  
   59.33 -EXTRA_DIST=icon16.png icon22.png icon32.png
   59.34 +EXTRA_DIST=icon16.png icon22.png icon32.png update.js.in
   59.35 +CLEANFILES=update.js
    60.1 --- a/update/resources.rc.in	Fri Mar 23 20:29:50 2012 +0000
    60.2 +++ b/update/resources.rc.in	Sat Nov 15 19:04:45 2014 +0000
    60.3 @@ -1,6 +1,8 @@
    60.4  #include <winver.h>
    60.5  #include <winuser.h>
    60.6  
    60.7 +#pragma code_page(65001)
    60.8 +
    60.9  MAINICON ICON "update.ico"
   60.10  
   60.11  VS_VERSION_INFO VERSIONINFO
   60.12 @@ -20,7 +22,7 @@
   60.13  		VALUE "FileVersion","@PACKAGE_VERSION@"
   60.14  		VALUE "InternalName","update"
   60.15  		VALUE "LegalCopyright",
   60.16 -		  "Copyright (c) 2009,2011,2012 J. Ali Harlow et al"
   60.17 +		  "Copyright © 2009,2011,2012 J. Ali Harlow et al"
   60.18  		VALUE "OriginalFilename","update.exe"
   60.19  		VALUE "ProductName","plover"
   60.20  		VALUE "ProductVersion","@PACKAGE_VERSION@"
    61.1 --- a/update/update.c	Fri Mar 23 20:29:50 2012 +0000
    61.2 +++ b/update/update.c	Sat Nov 15 19:04:45 2014 +0000
    61.3 @@ -27,18 +27,20 @@
    61.4  
    61.5  void update(const char *argv0)
    61.6  {
    61.7 -    char *path,*s,*prefix;
    61.8 +    char *path;
    61.9 +    gchar *s,*prefix;
   61.10      int ch;
   61.11      struct comps *comps;
   61.12 +    GError *error=NULL;
   61.13      path=plover_get_program_directory(argv0);
   61.14 -    s=plover_strconcat(path,"/repodata/comps.xml",NULL);
   61.15 +    s=g_strconcat(path,"/repodata/comps.xml",NULL);
   61.16      comps=plover_comps_new_from_file(s);
   61.17      if (!comps)
   61.18      {
   61.19  	perror(s);
   61.20  	exit(1);
   61.21      }
   61.22 -    free(s);
   61.23 +    g_free(s);
   61.24      prefix=plover_default_prefix_for_vendor(comps->vendor);
   61.25      if (!plover_installed_files_match_prefix(prefix))
   61.26      {
   61.27 @@ -50,11 +52,21 @@
   61.28  	    exit(1);
   61.29  	while(ch!='\n' && ch!=EOF)
   61.30  	    ch=getchar();
   61.31 -	plover_remove(NULL);
   61.32 +	if (plover_remove(NULL,&error))
   61.33 +	{
   61.34 +	    fprintf(stderr,"%s\n",error->message);
   61.35 +	    g_error_free(error);
   61.36 +	    exit(1);
   61.37 +	}
   61.38      }
   61.39      plover_comps_free(comps);
   61.40 -    plover_update(path,prefix,NULL);
   61.41 -    free(prefix);
   61.42 +    if (!plover_update(path,prefix,NULL,&error))
   61.43 +    {
   61.44 +	fprintf(stderr,"%s\n",error->message);
   61.45 +	g_error_free(error);
   61.46 +	exit(1);
   61.47 +    }
   61.48 +    g_free(prefix);
   61.49      free(path);
   61.50  }
   61.51  
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/update/update.js.in	Sat Nov 15 19:04:45 2014 +0000
    62.3 @@ -0,0 +1,68 @@
    62.4 +var WshShell = WScript.CreateObject("WScript.Shell");
    62.5 +var ScriptPath = WScript.ScriptFullName.replace(/\\[^\\]*$/, "");
    62.6 +var FileSystemObject = new ActiveXObject("Scripting.FileSystemObject");
    62.7 +
    62.8 +function RunUpdate(args)
    62.9 +{
   62.10 +    var OKButton = 0, ErrorIcon = 16, ForReading = 1;
   62.11 +    var path, command, i, ExecObject, text;
   62.12 +    path = FileSystemObject.BuildPath(ScriptPath, "update.exe");
   62.13 +    command = "\"" + path + "\"";
   62.14 +    for(i = 0; i < args.Length; i++)
   62.15 +	command += " \"" + args.Item(i) + "\"";
   62.16 +    ExecObject = WshShell.Exec(command);
   62.17 +    if (!ExecObject.StdErr.AtEndOfStream)
   62.18 +    {
   62.19 +	text = "Update failed for an unexpected reason. Please report "
   62.20 +	  + "the following error to support@city-occupational.co.uk:\n\n"
   62.21 +	  + ExecObject.StdErr.ReadAll();
   62.22 +	WshShell.Popup(text, 0, "Update failed", OKButton + ErrorIcon);
   62.23 +	return false;
   62.24 +    }
   62.25 +    else if (ExecObject.ExitCode)
   62.26 +    {
   62.27 +	text = "Update failed without giving a reason. Please report "
   62.28 +	  + "this to support@city-occupational.co.uk";
   62.29 +	WshShell.Popup(text, 0, "Update failed", OKButton + ErrorIcon);
   62.30 +	return false;
   62.31 +    }
   62.32 +    return true;
   62.33 +}
   62.34 +
   62.35 +function Update()
   62.36 +{
   62.37 +    var path;
   62.38 +    path = FileSystemObject.BuildPath(ScriptPath, "pre-inst.exe");
   62.39 +    WshShell.Run("\"" + path + "\"" + " --post \"wscript.exe"
   62.40 +      + " \\\"" + WScript.ScriptFullName + "\\\""
   62.41 +      + " --post %INSTALL_PREFIX% %TEST_RESULT%\"",
   62.42 +      7, true);
   62.43 +}
   62.44 +
   62.45 +function PostUpdate()
   62.46 +{
   62.47 +    var OKButton = 0, InfoIcon = 64, text;
   62.48 +    var test_result, install_prefix, path, args;
   62.49 +    install_prefix = WScript.Arguments.Item(1);
   62.50 +    test_result = WScript.Arguments.Item(2);
   62.51 +    if (test_result == "pass")
   62.52 +    {
   62.53 +	path = FileSystemObject.BuildPath(install_prefix,
   62.54 +	  "bin\\app-manager.exe");
   62.55 +	WshShell.Run("\"" + path + "\" --update \"" + ScriptPath + "\"");
   62.56 +    }
   62.57 +    else
   62.58 +    {
   62.59 +	args = { Length:0, Item:function(){return nil} };
   62.60 +	if (RunUpdate(args))
   62.61 +	{
   62.62 +	    text = "Software update completed successfully.";
   62.63 +	    WshShell.Popup(text, 0, "Software Update", OKButton + InfoIcon);
   62.64 +	}
   62.65 +    }
   62.66 +}
   62.67 +
   62.68 +if (WScript.Arguments.Length < 1)
   62.69 +    Update()
   62.70 +else if (WScript.Arguments.Length >= 3 && WScript.Arguments.Item(0) == "--post")
   62.71 +    PostUpdate()