From f88373ea1237fbff5188f8db68f18fb0b0a0ced5cf5ef57e059b9135dbb0a1fd Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Mon, 4 Jun 2012 17:38:43 +0000 Subject: [PATCH] Accepting request 122025 from home:gberh:branches:GNOME:Factory - Rewrote SuSEconfig.glib2 to support different default MIME associations for different desktops. It reads /etc/{gnome,xfce,lxde}_defaults.desktop to produce /var/cache/gio-2.0/{gnome,xfce,lxde}-defaults.list which can then be symlinked for each desktop to a directory in $XDG_DATA_DIRS. OBS-URL: https://build.opensuse.org/request/show/122025 OBS-URL: https://build.opensuse.org/package/show/GNOME:Factory/glib2?expand=0&rev=197 --- SuSEconfig.glib2 | 365 ++++++++++++++++++++++++++++++----------------- glib2.changes | 9 ++ glib2.spec | 10 +- 3 files changed, 248 insertions(+), 136 deletions(-) diff --git a/SuSEconfig.glib2 b/SuSEconfig.glib2 index 61fcce0..33ad2b7 100644 --- a/SuSEconfig.glib2 +++ b/SuSEconfig.glib2 @@ -1,144 +1,243 @@ -#! /bin/sh +#!/bin/sh # -# Copyright (c) 2006, 2008 SuSE -# Author: Stanislav Brabec +# SuSEconfig.glib2 - create default application ordering for MIME associations # -# Creates defaults.list from gnome_defaults.conf using only available -# applications and preferring GNOME and GTK applications. +# Copyright (C) 2012 Guido Berhoerster +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# TORTIOUS ACTION, ARISING OUT OF PERFORMANCE OF THIS SOFTWARE. # -# See /etc/gnome_defaults.conf for algorithm description. -shopt -s nullglob +export LC_ALL=C -unset DUMMY ${!MIME_*} ${!APP_*} ${!DEFAULT_*} ${!PREFDEFAULT_*} ${!DEFDESKTOP_*} - -# Ensure, that $XDG_DATA_DIRS is set properly. (#71978, #240603) -if test "$PROFILEREAD" != true ; then - . $r/etc/profile +# reset XDG_DATA_DIRS so it can be trusted +unset XDG_DATA_DIRS +if [ "${PROFILEREAD}" != "true" ]; then + . $r/etc/profile fi -# Read defaults.list and set applications as best candidates. -exec <$r/etc/gnome_defaults.conf -while read ; do - case "$REPLY" in - "#"* | "" ) - ;; - # Is is default application for particular MIME type? - *=* ) - # Strip optional priority record (and ignore it - no GNOME app uses it). - MIME=${REPLY%%=*} - # Replace special characters. - MIMES=${MIME//_/__} - MIMES=${MIMES//\//_S} - MIMES=${MIMES//-/_M} - MIMES=${MIMES//+/_P} - MIMES=${MIMES//./_D} - eval DEFAULT_${MIMES}\=${REPLY#*=} - ;; - # Is it preferred default application? - !* ) - DESKTOP=${REPLY#!} - DESKTOPS=${DESKTOP//_/__} - DESKTOPS=${DESKTOPS//-/_M} - DESKTOPS=${DESKTOPS//+/_P} - DESKTOPS=${DESKTOPS//./_D} - DESKTOPS=${DESKTOPS// /_S} - DESKTOPS=${DESKTOPS//:/_C} - eval DEFDESKTOP_$DESKTOPS\=PREFDEFAULT - ;; - # Is it default application? - * ) - DESKTOP=${REPLY} - DESKTOPS=${DESKTOP//_/__} - DESKTOPS=${DESKTOPS//-/_M} - DESKTOPS=${DESKTOPS//+/_P} - DESKTOPS=${DESKTOPS//./_D} - DESKTOPS=${DESKTOPS// /_S} - DESKTOPS=${DESKTOPS//:/_C} - eval DEFDESKTOP_$DESKTOPS\=DEFAULT - ;; - esac -done -exec <&- +for desktop in gnome xfce lxde; do + awk -vdesktop=${desktop} ' +# print a warning to stderr +function warn(msg, cmd) { + cmd = "cat >&2" + print msg | cmd + close(cmd) +} -IFS="$IFS:;" -# Browse all desktop files -for DIR in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share} ; do - for DESKTOP in $r$DIR/applications/*.desktop ; do - DESKTOPN=${DESKTOP##*/} - DESKTOPS=${DESKTOPN//_/__} - DESKTOPS=${DESKTOPS//-/_M} - DESKTOPS=${DESKTOPS//+/_P} - DESKTOPS=${DESKTOPS//./_D} - DESKTOPS=${DESKTOPS// /_S} - DESKTOPS=${DESKTOPS//:/_C} - IS_DEFAULT_DESKTOP=false - eval "if test \"\$DEFDESKTOP_$DESKTOPS\" ; then - IS_DEFAULT_DESKTOP=true - DEFTYPE=\$DEFDESKTOP_$DESKTOPS - fi" - exec <"$DESKTOP" - CATEGORIES= - MIMETYPE= - while read ; do - case "$REPLY" in - Categories=* ) - CATEGORIES="${REPLY#Categories=}" - ;; - MimeType=* ) - MIMETYPE="${REPLY#MimeType=}" - ;; - esac - done - exec <&- - # Is it a GNOME application? - APPTYPE=GENERIC - if test "$CATEGORIES" != "${CATEGORIES/GTK}" ; then - APPTYPE=GTK - fi - if test "$CATEGORIES" != "${CATEGORIES/GNOME}" ; then - APPTYPE=GNOME - fi - if $IS_DEFAULT_DESKTOP ; then - APPTYPE=$DEFTYPE - fi - for MIME in $MIMETYPE ; do - # Strip optional priority record (and ignore it - no GNOME app uses it). - MIME=${MIME%:*} - # Replace special characters. - MIMES=${MIME//_/__} - MIMES=${MIMES//\//_S} - MIMES=${MIMES//-/_M} - MIMES=${MIMES//+/_P} - MIMES=${MIMES//./_D} - eval MIME_$MIMES\=$MIME - IS_DEFAULT=false - eval "if test \"\$DEFAULT_$MIMES\" = \"\$DESKTOPN\" ; then - IS_DEFAULT=true - fi" - if $IS_DEFAULT ; then - eval APP_MIMEDEFAULT_$MIMES\=\"\$DESKTOPN\" - else - eval APP_${APPTYPE}_$MIMES\=\"\$DESKTOPN\" - fi - done - done -done +# print an error message and exit with the given exit status +function err(status, msg) +{ + warn(msg) + exit_status = status + exit exit_status +} -exec >$r/var/cache/gio-2.0/defaults.list -echo "# generated by SuSEconfig --module glib2 from /etc/gnome_defaults.conf" -echo "[Default Applications]" +# delete all elements of an array +function delete_array(arr, i) { + for (i in arr) { + delete arr[i] + } +} -# Browse all offered MIME types and write defaults.list. -for MIMES in ${!MIME_*} ; do - eval MIME\=\$$MIMES - MIMES=${MIMES#MIME_} - # Try GNOME applications first, then GTK, then generic. - for APPTYPE in MIMEDEFAULT PREFDEFAULT DEFAULT GNOME GTK GENERIC ; do - eval "if test \"\$APP_${APPTYPE}_$MIMES\" ; then - echo \"$MIME=\$APP_${APPTYPE}_$MIMES\" ; - break ; - fi" - done +# find preferred combination of mimetype and category +function find_preferred_category(mimetypes_categories, categories, mimetype, + i) { + for (i = 1; i in categories; i++) { + if (mimetype SUBSEP categories[i] in mimetypes_categories) { + return mimetypes_categories[mimetype,categories[i]] + } + } +} + +# sort keys of an array by index (using the awk default comparison) +function asorti2(src, dest, key, len) { + len = 0 + delete_array(dest) + for (key in src) { + dest[len++] = key + } + + _qsorti(dest, 0, len - 1); +} + +function array_swap(arr, i, j, tmp) { + tmp = arr[i] + arr[i] = arr[j] + arr[j] = tmp +} + +# Based on Bentley, J. L., 2000. Programming Pearls. 2nd ed. Reading, MA: +# Addison-Wesley Professional. +function _qsorti(dest, l, u, val, i, j) { + if (l >= u) { + return + } + + array_swap(dest, l, l + int(rand() * (u - l))) + val = dest[l] + i = l + j = u + 1 + while (1) { + do { i++ } while (i <= u && dest[i] < val) + do { j-- } while (dest[j] > val) + if (i > j) { + break + } + array_swap(dest, i, j) + } + array_swap(dest, l, j) + + _qsorti(dest, l, j - 1) + _qsorti(dest, j + 1, u) +} + +BEGIN { + desktop = desktop != "" ? desktop : "gnome" + if (desktop == "gnome") { + categories_list = "GNOME,GTK" + } else if (desktop == "xfce") { + categories_list = "XFCE,GTK" + } else if (desktop == "lxde") { + categories_list = "GTK" + } + split(categories_list, categories, /,/) + root = ENVIRON["r"] + defaults_conf = root "/etc/" desktop "_defaults.conf" + + # parse desktop defaults preferences + lineno = 0 + while ((getline < defaults_conf) > 0) { + lineno++ + if (NF == 0 || $1 ~ /^#/) { + # skip comments and empty lines + continue + } else if (NF != 1) { + err(1, "syntax error in " defaults_conf " line " lineno) + } else if (split($1, arr, /=/) == 2) { + # handle MIME type defaults + mimetype_default_apps[arr[1]] = arr[2] + } else if ($1 ~ /^!.+\.desktop$/) { + # handle preferred default applications + preferred_default_apps[substr($1, 2)] = substr($1, 2) + } else if ($1 ~ /^.+\.desktop$/) { + # handle regular default applications + default_apps[$1] = $1 + } else { + err(1, "syntax error in " defaults_conf ", line " lineno) + } + } + close(defaults_conf) + + # find all desktop files + for (i = split("XDG_DATA_DIRS" in ENVIRON ? ENVIRON["XDG_DATA_DIRS"] : \ + "/usr/local/share:/usr/share", xdg_data_dirs, /:/); i > 0; i--) { + # XDG_DATA_DIRS is trusted here because it has been reset + cmd = "ls -1 -- \"" root xdg_data_dirs[i] "/applications/\"*.desktop " \ + "2>/dev/null" + while ((cmd | getline desktopfile) > 0) { + l = split(desktopfile, arr, "/") + desktopfiles[arr[l]] = desktopfile + } + close(cmd) + } + + # process all desktop files in alphabetical order + asorti2(desktopfiles, desktopfiles_keys) + for (i = 0; i in desktopfiles_keys; i++) { + # parse a desktop file + desktopfile = desktopfiles_keys[i] + delete_array(desktopfile_mimetypes) + delete_array(desktopfile_categories) + lineno = 0 + in_desktop_entry = 0 + while ((getline < desktopfiles[desktopfile]) > 0) { + lineno++ + if (NF == 0 || $1 ~ /^#/) { + # skip comments and empty lines + continue + } else if (in_desktop_entry == 0 && \ + $0 ~ /^\[Desktop Entry\][\t ]*$/) { + # desktop entry group + in_desktop_entry = 1 + } else if (in_desktop_entry == 1) { + if (in_desktop_entry == 1 && $1 ~ /^\[/) { + # quit when a different group starts, "Desktop Entry" must + # come first + break + } else if ($0 ~ /^MimeType *=/ && split($0, arr, /=/) == 2) { + # handle MimeTypes + gsub(/(^ *|; *$)/, "", arr[2]) + split(arr[2], desktopfile_mimetypes, /;/) + } else if ($0 ~ /^Categories *=/ && split($0, arr, /=/) == 2) { + # handle Categories + gsub(/(^ *|; *$)/, "", arr[2]) + split(arr[2], desktopfile_categories, /;/) + } else if ($0 ~ /^[A-Za-z0-9\[\]@_-]+ *=/) { + # skip other keys + continue + } + } else { + warn("syntax error in " desktopfiles[desktopfile] ", line " \ + lineno) + break + } + } + close(desktopfiles[desktopfile]) + + # store the results + for (j = 1; j in desktopfile_mimetypes; j++) { + if (desktopfile_mimetypes[j] in mimetype_default_apps && \ + mimetype_default_apps[desktopfile_mimetypes[j]] == \ + desktopfile) { + mimetype_defaults[desktopfile_mimetypes[j]] = desktopfile + } + if (desktopfile in preferred_default_apps) { + preferred_defaults[desktopfile_mimetypes[j]] = desktopfile + } + if (desktopfile in default_apps) { + defaults[desktopfile_mimetypes[j]] = desktopfile + } + for (k = 1; k in desktopfile_categories; k++) { + mimetypes_categories[desktopfile_mimetypes[j], \ + desktopfile_categories[k]] = desktopfile + } + generic_mimetypes[desktopfile_mimetypes[j]] = desktopfile + } + } + + # determine default mimetype handlers + for (mimetype in generic_mimetypes) { + if (mimetype in mimetype_defaults) { + defaults_list[mimetype] = mimetype_defaults[mimetype] + } else if (mimetype in preferred_defaults) { + defaults_list[mimetype] = preferred_defaults[mimetype] + } else if (mimetype in defaults) { + defaults_list[mimetype] = defaults[mimetype] + } else if ((desktopfile = \ + find_preferred_category(mimetypes_categories, categories, \ + mimetype)) != "") { + defaults_list[mimetype] = desktopfile + } else if (mimetype in generic_mimetypes) { + defaults_list[mimetype] = generic_mimetypes[mimetype] + } + } + + print "# generated by SuSEconfig --module glib2 from " defaults_conf + print "[Default Applications]" + asorti2(defaults_list, defaults_list_keys) + for (i = 0; i in defaults_list_keys; i++) { + mimetype = defaults_list_keys[i] + printf("%s=%s\n", mimetype, defaults_list[mimetype]) + } +} +' >$r/var/cache/gio-2.0/${desktop}-defaults.list done -exec >&- diff --git a/glib2.changes b/glib2.changes index e43bf2f..20800c5 100644 --- a/glib2.changes +++ b/glib2.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri May 18 13:56:57 UTC 2012 - gber@opensuse.org + +- Rewrote SuSEconfig.glib2 to support different default MIME + associations for different desktops. It reads + /etc/{gnome,xfce,lxde}_defaults.desktop to produce + /var/cache/gio-2.0/{gnome,xfce,lxde}-defaults.list which can then + be symlinked for each desktop to a directory in $XDG_DATA_DIRS. + ------------------------------------------------------------------- Tue May 15 09:52:49 UTC 2012 - dimstar@opensuse.org diff --git a/glib2.spec b/glib2.spec index 2ce40f0..65593a5 100644 --- a/glib2.spec +++ b/glib2.spec @@ -295,8 +295,10 @@ install -D -m0755 SuSEconfig.glib2 %{buildroot}/sbin/conf.d/SuSEconfig.glib2 install -D -m0644 gnome_defaults.conf %{buildroot}%{_sysconfdir}/gnome_defaults.conf # default apps magic mkdir -p %{buildroot}%{_localstatedir}/cache/gio-2.0 %{buildroot}%{_datadir}/applications -touch %{buildroot}%{_localstatedir}/cache/gio-2.0/defaults.list -ln -s %{_localstatedir}/cache/gio-2.0/defaults.list %{buildroot}%{_datadir}/applications/defaults.list +touch %{buildroot}%{_localstatedir}/cache/gio-2.0/gnome-defaults.list +touch %{buildroot}%{_localstatedir}/cache/gio-2.0/xfce-defaults.list +touch %{buildroot}%{_localstatedir}/cache/gio-2.0/lxde-defaults.list +ln -s %{_localstatedir}/cache/gio-2.0/gnome-defaults.list %{buildroot}%{_datadir}/applications/defaults.list # gio-querymodules magic %if "%{_lib}" == "lib64" mv %{buildroot}%{_bindir}/gio-querymodules %{buildroot}%{_bindir}/gio-querymodules-64 @@ -427,7 +429,9 @@ rm -rf %{buildroot} %ghost %{_datadir}/glib-2.0/schemas/gschemas.compiled %{_datadir}/applications/defaults.list %dir %{_localstatedir}/cache/gio-2.0 -%ghost %{_localstatedir}/cache/gio-2.0/defaults.list +%ghost %{_localstatedir}/cache/gio-2.0/gnome-defaults.list +%ghost %{_localstatedir}/cache/gio-2.0/xfce-defaults.list +%ghost %{_localstatedir}/cache/gio-2.0/lxde-defaults.list %files -n libgio-fam %defattr(-,root,root)