Commits

jjacky committed 720d597

couple of bugfixes: saving data could silently fail; $INS missing in template Title

- when saving data (marking (AUR) watched packages, read news, managing (AUR) watched packages) would silently failed if the folder did not exists (yet kalu acted as if it had worked), which was pretty much always the case on a new installation, fixed
- template Title was missing $INS (total install size), fixed

Comments (0)

Files changed (6)

 
 #define _UNUSED_            __attribute__ ((unused)) 
 
-#define KALU_VERSION       "0.0.1"
+#define KALU_VERSION       "0.0.2"
 
 #define MAX_PATH            255
 
         size_h = humanize_size (nsize, '\0', &unit);
         snprintf (buf, 255, "%.2f %s", size_h, unit);
         replacements[2]->value = strdup (buf);
-        replacements[3] = NULL;
+        replacements[3] = (replacement_t *) malloc (sizeof (*replacements));
+        replacements[3]->name = "INS";
+        size_h = humanize_size (isize, '\0', &unit);
+        snprintf (buf, 255, "%.2f %s", size_h, unit);
+        replacements[3]->value = strdup (buf);
+        replacements[4] = NULL;
     }
     
     parse_tpl (template.title, &summary, &len, &alloc, replacements);
     {
         free (replacements[1]->value);
         free (replacements[2]->value);
+        free (replacements[3]->value);
         free (replacements[1]);
         free (replacements[2]);
+        free (replacements[3]);
     }
     
     NotifyNotification *notification;
 #include "kalu.h"
 #include "news.h"
 #include "curl.h"
+#include "util.h"
+#include "util-gtk.h"
 
 #define NEWS_RSS_URL        "http://www.archlinux.org/feeds/news/"
 
 btn_mark_cb (GtkWidget *button _UNUSED_, GtkWidget *window)
 {
     alpm_list_t **lists, *titles_all, *titles_shown, *titles_read, *i;
+    alpm_list_t *news_read = NULL;
+    char *news_last = NULL;
     gboolean is_last_set = FALSE;
     int nb_unread = 0;
     
+    gtk_widget_hide (window);
+    
     lists = g_object_get_data (G_OBJECT (window), "lists");
     /* reverse this one, to start with the oldest news */
     titles_all = alpm_list_reverse (lists[LIST_TITLES_ALL]);
     titles_shown = lists[LIST_TITLES_SHOWN];
     titles_read = lists[LIST_TITLES_READ];
     
-    /* reset list of read news */
-    FREELIST (config->news_read);
-    
     for (i = titles_all; i; i = alpm_list_next (i))
     {
         void *shown = alpm_list_find_ptr (titles_shown, i->data);
             {
                 /* then we add it to read */
                 debug ("read:%s", (char*)i->data);
-                config->news_read = alpm_list_add (config->news_read, strdup (i->data));
+                news_read = alpm_list_add (news_read, strdup (i->data));
             }
             else
             {
                 /* set the new last */
-                if (config->news_last)
+                if (news_last)
                 {
-                    free (config->news_last);
+                    free (news_last);
                 }
                 debug ("last=%s", (char*)i->data);
-                config->news_last = strdup (i->data);
+                news_last = strdup (i->data);
             }
         }
         /* was it shown? i.e. stays unread */
     /* save */
     FILE *fp;
     char file[MAX_PATH];
+    gboolean saved = FALSE;
     
     snprintf (file, MAX_PATH - 1, "%s/.config/kalu/news.conf", g_get_home_dir ());
-    fp = fopen (file, "w");
-    if (fp != NULL)
+    if (ensure_path (file))
     {
-        fputs ("Last=", fp);
-        fputs (config->news_last, fp);
-        fputs ("\n", fp);
-        
-        for (i = config->news_read; i; i = alpm_list_next (i))
+        fp = fopen (file, "w");
+        if (fp != NULL)
         {
-            fputs ("Read=", fp);
-            fputs ((const char *) i->data, fp);
+            fputs ("Last=", fp);
+            fputs (news_last, fp);
             fputs ("\n", fp);
+            
+            for (i = news_read; i; i = alpm_list_next (i))
+            {
+                fputs ("Read=", fp);
+                fputs ((const char *) i->data, fp);
+                fputs ("\n", fp);
+            }
+            fclose (fp);
+            
+            /* update */
+            if (config->news_last)
+            {
+                free (config->news_last);
+            }
+            config->news_last = news_last;
+            
+            FREELIST (config->news_read);
+            config->news_read = news_read;
+            
+            set_kalpm_nb (CHECK_NEWS, nb_unread);
+            saved = TRUE;
         }
-        fclose (fp);
     }
-    set_kalpm_nb (CHECK_NEWS, nb_unread);
     
-    gtk_widget_destroy (window);
+    if (saved)
+    {
+        gtk_widget_destroy (window);
+    }
+    else
+    {
+        gtk_widget_show (window);
+        show_error ("Unable to save changes to disk", file, GTK_WINDOW (window));
+    }
 }
 
 static void
 #include <dirent.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 /* alpm */
 #include <alpm_list.h>
 #include "kalu.h"
 #include "util.h"
 
+/**
+ * Makes sure the path for the filename exists. that is, makes sure every
+ * bits before the last / exists and is a folder
+ */
+gboolean
+ensure_path (char *path)
+{
+    char *s, *p, org;
+    struct stat stat_info;
+    
+    p = path + 1; /* skip the root */
+    while ((s = strchr (p, '/')))
+    {
+        *s = '\0';
+        if (0 != stat(path, &stat_info))
+        {
+            /* if does not exist, we create it */
+            if (errno == ENOENT)
+            {
+                debug ("mkdir %s", path);
+                if (0 != mkdir (path, S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))
+                {
+                    *s = '/'; /* restore */
+                    return FALSE;
+                }
+            }
+            else
+            {
+                debug ("failed to stat %s: %s", path, strerror (errno));
+                *s = '/'; /* restore */
+                return FALSE;
+            }
+        }
+        /* make sure it's a folder */
+        else if (!S_ISDIR(stat_info.st_mode))
+        {
+            *s = '/'; /* restore */
+            return FALSE;
+        }
+        *s = '/'; /* restore */
+        p = s + 1;
+    }
+    return TRUE;
+}
+
 /*******************************************************************************
  * The following functions come from pacman's source code. (They might have
  * been (slightly) modified.)
     char *value;
 } replacement_t;
 
+gboolean
+ensure_path (char *path);
+
 char *
 strtrim (char *str);
 
     }
 }
 
-static void
-save_watched (gboolean is_aur)
+static gboolean
+save_watched (gboolean is_aur, alpm_list_t *new_watched)
 {
     FILE *fp;
     char file[MAX_PATH];
-    alpm_list_t *list, *i;
+    alpm_list_t *i;
+    gboolean success = FALSE;
     
     if (is_aur)
     {
         snprintf (file, MAX_PATH - 1, "%s/.config/kalu/watched-aur.conf", g_get_home_dir ());
-        list = config->watched_aur;
     }
     else
     {
         snprintf (file, MAX_PATH - 1, "%s/.config/kalu/watched.conf", g_get_home_dir ());
-        list = config->watched;
     }
     
-    fp = fopen (file, "w");
-    if (fp == NULL)
+    if (ensure_path (file))
     {
-        return;
+        fp = fopen (file, "w");
+        if (fp != NULL)
+        {
+            for (i = new_watched; i; i = alpm_list_next (i))
+            {
+                watched_package_t *w_pkg = i->data;
+                fputs (w_pkg->name, fp);
+                fputs ("=", fp);
+                fputs (w_pkg->version, fp);
+                fputs ("\n", fp);
+            }
+            
+            fclose (fp);
+            success = TRUE;
+        }
     }
     
-    for (i = list; i; i = alpm_list_next (i))
-    {
-        watched_package_t *w_pkg = i->data;
-        fputs (w_pkg->name, fp);
-        fputs ("=", fp);
-        fputs (w_pkg->version, fp);
-        fputs ("\n", fp);
-    }
-    
-    fclose (fp);
+    return success;
 }
 
 static int
     GtkTreeIter iter;
     gboolean upd;
     gchar *new;
-    watched_package_t *w_pkg, w_pkg_tmp;
+    watched_package_t *w_pkg, *w_pkg2, w_pkg_tmp;
     alpm_list_t *updates = NULL;
     int nb_watched = 0;
     GtkWidget *window_notif, *window_manage;
-    alpm_list_t *cfglist;
+    alpm_list_t *cfglist, *i, *new_watched = NULL;
     
     if (is_aur)
     {
     
     gtk_widget_hide (window_notif);
     
+    /* duplicate the list */
+    for (i = cfglist; i; i = alpm_list_next (i))
+    {
+        w_pkg = i->data;
+        w_pkg2 = calloc (1, sizeof (*w_pkg2));
+        w_pkg2->name = w_pkg->name;
+        w_pkg2->version = w_pkg->version;
+        new_watched = alpm_list_add (new_watched, w_pkg2);
+    }
+    
     if (gtk_tree_model_get_iter_first (model, &iter))
     {
         while (1)
                     WCOL_NEW_VERSION, &new,
                     -1);
                 /* find this package/version */
-                w_pkg = alpm_list_find (cfglist, &w_pkg_tmp,
+                w_pkg = alpm_list_find (new_watched, &w_pkg_tmp,
                     (alpm_list_fn_cmp) watched_package_cmp);
                 if (NULL != w_pkg)
                 {
     }
     
     /* save to file */
-    save_watched (is_aur);
-    
-    /* manage window needs an update? */
-    if (window_manage != NULL && updates != NULL)
+    if (save_watched (is_aur, new_watched))
     {
-        GtkWidget *dialog;
-        dialog = new_confirm ("Do you want to import marked changes into the current list?",
-                              "You have marked one or more packages with updated version number since starting the editing of this list.",
-                              "Yes, import changes.", NULL,
-                              "No, keep the list as is.", NULL,
-                              window_manage);
-        g_object_set_data (G_OBJECT (dialog), "is-aur", (gpointer) is_aur);
-        g_signal_connect (G_OBJECT (dialog), "response",
-                          G_CALLBACK (monitor_response_cb), (gpointer) updates);
-        gtk_widget_show (dialog);
+        /* manage window needs an update? */
+        if (window_manage != NULL && updates != NULL)
+        {
+            GtkWidget *dialog;
+            dialog = new_confirm ("Do you want to import marked changes into the current list?",
+                                  "You have marked one or more packages with updated version number since starting the editing of this list.",
+                                  "Yes, import changes.", NULL,
+                                  "No, keep the list as is.", NULL,
+                                  window_manage);
+            g_object_set_data (G_OBJECT (dialog), "is-aur", (gpointer) is_aur);
+            g_signal_connect (G_OBJECT (dialog), "response",
+                              G_CALLBACK (monitor_response_cb), (gpointer) updates);
+            gtk_widget_show (dialog);
+        }
+        else
+        {
+            alpm_list_free (updates);
+        }
+        
+        /* done */
+        set_kalpm_nb ((is_aur) ? CHECK_WATCHED_AUR : CHECK_WATCHED, nb_watched);
+        gtk_widget_destroy (window_notif);
     }
     else
     {
-        alpm_list_free (updates);
+        gtk_widget_show (window_notif);
+        show_error ("Unable to save changes to disk", NULL, GTK_WINDOW (window_notif));
     }
     
-    /* done */
-    set_kalpm_nb ((is_aur) ? CHECK_WATCHED_AUR : CHECK_WATCHED, nb_watched);
-    gtk_widget_destroy (window_notif);
+    /* free duplicate list */
+    FREELIST (new_watched);
 }
 
 static void
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
+    GtkWidget *window;
     watched_package_t *w_pkg;
-    alpm_list_t **cfglist;
+    alpm_list_t **cfglist, *new_watched = NULL;
     
     if (is_aur)
     {
+        window = watched.window_manage_aur;
         model = gtk_tree_view_get_model (GTK_TREE_VIEW (watched.tree_manage_aur));
         cfglist = &(config->watched_aur);
     }
     else
     {
+        window = watched.window_manage;
         model = gtk_tree_view_get_model (GTK_TREE_VIEW (watched.tree_manage));
         cfglist = &(config->watched);
     }
     
-    /* clear watched list in memory */
-    FREE_WATCHED_PACKAGE_LIST (*cfglist);
+    gtk_widget_hide (window);
     
-    /* make up new one */
+    /* make up new list */
     if (gtk_tree_model_get_iter_first (model, &iter))
     {
         while (1)
             w_pkg = calloc (1, sizeof (*w_pkg));
             w_pkg->name = strdup ((name) ? name : "-");
             w_pkg->version = strdup ((version) ? version : "0");
-            *cfglist = alpm_list_add (*cfglist, w_pkg);
+            new_watched = alpm_list_add (new_watched, w_pkg);
             /* next */
             if (!gtk_tree_model_iter_next (model, &iter))
             {
             }
         }
     }
+    
     /* save it */
-    save_watched (is_aur);
-    
-    /* done */
-    if (is_aur)
+    if (save_watched (is_aur, new_watched))
     {
-        gtk_widget_destroy (watched.window_manage_aur);
+        /* clear watched list in memory */
+        FREE_WATCHED_PACKAGE_LIST (*cfglist);
+        
+        /* apply */
+        *cfglist = new_watched;
+        
+        /* done */
+        gtk_widget_destroy (window);
     }
     else
     {
-        gtk_widget_destroy (watched.window_manage);
+        /* free */
+        FREE_WATCHED_PACKAGE_LIST (new_watched);
+        
+        gtk_widget_show (window);
+        show_error ("Unable to save changes to disk", NULL, GTK_WINDOW (window));
     }
 }