ALT Linux Team development discussions
 help / color / mirror / Atom feed
From: Alexey Tourbin <at@altlinux.ru>
To: devel@lists.altlinux.org
Subject: [devel] posttrans filetriggers [2]
Date: Mon, 8 Sep 2008 13:51:06 +0400
Message-ID: <20080908095106.GS6477@altlinux.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 10349 bytes --]

Юрий Седунов просил меня реализовать posttrans filetriggers,
чтобы решить проблему c gtk icon cache в branch-4.1 (для предостящего
релиза дистрибутива).

Проблема это такая: библиотека libgtk+2 может использовать кеш
иконок /usr/share/icons/hicolor/icon-theme.cache, чтобы ускорить
загрузку иконок.  По умолчанию этот кеш отсутствует; но если он создан,
то libgtk+2 не находит иконки, отсутствующие в кеше (но существующие в
файловой системе).

Пакет NetworkManager-gnome создаёт/обновляет этот кеш, а большая часть
других пакетов (около 700+ штук) не создаёт и не обновляет этот кеш.  Это
означает, что после установки NetworkManager-gnome библиотека libgtk+2
будет использовать кеш, созданный на стадии установки NetworkManager-gnome,
а установка дополнительных пакетов с иконками на этот кеш никак не
повлияет, то есть, в конечном счёте, в приложениях будут битые иконки.

Возможное решение проблемы -- добавить %post-скрипт для обновления кеша
иконок во все пакеты, которые содержат /usr/share/icons/hicolor/*.
Возражения:
1) Пачить 700+ штук пакетов -- мартышкин труд.
2) Пакеты с иконками не обязаны знать специфику работы libgtk+2 кеша,
и даже что он вообще есть.
3) Можно сэкономить время на установке, если создать/обновить кеш
только один раз, в конце транзакции.

Идея posttrans filetriggers простая -- во время выполнения транзакции
создаётся список установленных/удалённых файлов.  Дальше можно написать
скрипт, который, если транзакция успешно завершилась, получит на вход
этот список файлов и сможет выполнить определённые действия.

Упрощенный пример для обновления кеша иконок.

/usr/lib/rpm/gtk+2-icon-cache.filetrigger:
	#!/bin/sh
	if grep -qs ^/usr/share/icons/hicolor/; then
		gtk-update-icon-cache --force --ignore-theme-index
	fi

Упрощенный пример для регистрации GConf2 схем.

/usr/lib/rpm/GConf2-schemas.filetrigger:
	#!/bin/sh
	install=
	remove=
	while read -r f; do
		case "$f" in
			/etc/gconf/schemas/*.schemas) ;;
			*) continue ;;
		esac
		if [ -f "$f" ]; then
			install="$install $f"
		else
			remove="$remove $f"
		fi
	done
	[ -z "$install" ] || gconftool-2 --makefile-install-rule $install
	[ -z "$remove" ] || gconftool-2 --makefile-uninstall-rule $remove

Последний пример показывает, что можно реализовать достаточно сложные
случаи обработки аргументов, накапливая аргументы в цикле (чтобы
запустить прогрмму всего одни раз).  На самом деле в реальном скрипте
лучше использовать xargs --delimiter='\n', потому что argv может
переполниться, а файлы могут содержать пробелы).

В отличие от мандривовского патча, я не стал делать у файлов префиксы
"+" и "-", т.к. из-за особенностей librpm нельзя сделать чтобы это
хорошо работало (т.е. "+" может и не означать, что файл был добавлен,
а "-" может не означать, что файл таки был удалён).  В последнем примере
я просто явно проверяю [ -f "$f" ].

Changelog since common ancestor `4.0.4-alt95.M41.2' follows:
commit 462bd2a2b95b6946ccd347b8d1848943d5ae3c99
Author: Alexey Tourbin <at@altlinux>
Date:   Mon Sep 8 10:57:19 2008 +0400

    implemented posttrans filetriggers, vaguely based on Mandriva patch

Full diff since common ancestor `4.0.4-alt95.M41.2' follows:
diff --git a/a b/a
new file mode 100644
index 0000000..e69de29
diff --git a/configure.in b/configure.in
index 2e7b53e..82a959c 100644
--- a/configure.in
+++ b/configure.in
@@ -1022,6 +1022,7 @@ AC_OUTPUT([ Doxyfile Makefile rpmrc macros platform rpmpopt rpm.spec
 	scripts/strip_files
 	scripts/symlinks.req
 	scripts/verify-elf
+	scripts/posttrans-filetriggers
 	tests/Makefile tests/rpmrc tests/macros tests/hello-test/Makefile
 	po/Makefile.in
 	doc/Makefile doc/manual/Makefile
diff --git a/lib/psm.c b/lib/psm.c
index b9e6f8e..3ccaf60 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -900,7 +900,7 @@ static int runScript(PSM_t psm, Header h,
     int freePrefixes = 0;
     FD_t out;
     rpmRC rc = RPMRC_OK;
-    const char *n, *v, *r;
+    const char *n = NULL, *v = NULL, *r = NULL;
     char arg1_str [sizeof(int)*3+1] = "";
     char arg2_str [sizeof(int)*3+1] = "";
 
@@ -917,6 +917,7 @@ static int runScript(PSM_t psm, Header h,
 	argc = progArgc;
     }
 
+    if (h)
     xx = headerNVR(h, &n, &v, &r);
 
     if (arg1 >= 0)
@@ -924,9 +925,9 @@ static int runScript(PSM_t psm, Header h,
     if (arg2 >= 0)
 	sprintf(arg2_str, "%d", arg2);
 
-    if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
+    if (h && hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
 	freePrefixes = 1;
-    } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
+    } else if (h && hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
 	prefixes = &oldPrefix;
 	numPrefixes = 1;
     } else {
@@ -1038,6 +1039,7 @@ static int runScript(PSM_t psm, Header h,
 	    }
 	}
 
+	if (n)
 	dosetenv ("RPM_INSTALL_NAME", n, 1);
 
 	if (*arg1_str)
@@ -2130,3 +2132,58 @@ fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
     return rc;
     /*@=nullstate@*/
 }
+
+static
+void saveTriggerFiles(PSM_t psm)
+{
+    const rpmTransactionSet ts = psm->ts;
+    if (ts->transFlags & RPMTRANS_FLAG_TEST)
+	return;
+    if (ts->transFlags & (_noTransScripts | _noTransTriggers))
+	return;
+    const TFI_t fi = psm->fi;
+    if (fi->fc < 1)
+	return;
+    psmStage(psm, PSM_CHROOT_IN);
+    const char *file = rpmGetPath(ts->rpmdb->db_home, "/files-awaiting-filetriggers");
+    FILE *fp = fopen(file, "a");
+    if (fp == NULL)
+	rpmError(RPMERR_OPEN, "open of %s failed: %s\n", file, strerror(errno));
+    else {
+	int i;
+	for (i = 0; i < fi->fc; i++)
+	    fprintf(fp, "%s%s\n", fi->dnl[fi->dil[i]], fi->bnl[i]);
+	fclose(fp);
+    }
+    file = _free(file);
+    psmStage(psm, PSM_CHROOT_OUT);
+}
+
+void psmTriggerAdded(PSM_t psm)
+{
+    saveTriggerFiles(psm);
+}
+
+void psmTriggerRemoved(PSM_t psm)
+{
+    saveTriggerFiles(psm);
+}
+
+void psmTriggerPosttrans(PSM_t psm)
+{
+    const rpmTransactionSet ts = psm->ts;
+    if (ts->transFlags & RPMTRANS_FLAG_TEST)
+	return;
+    if (ts->transFlags & (_noTransScripts | _noTransTriggers))
+	return;
+    psmStage(psm, PSM_CHROOT_IN);
+    const char *file = rpmGetPath(ts->rpmdb->db_home, "/files-awaiting-filetriggers");
+    const char *script = RPMCONFIGDIR "/posttrans-filetriggers";
+    const char *argv[] = { script, file, NULL };
+    rpmMessage(RPMMESS_VERBOSE, _("Running %s\n"), script);
+    int rc = runScript(psm, NULL, script, 2, argv, NULL, 0, 0);
+    if (rc == 0)
+	unlink(file);
+    file = _free(file);
+    psmStage(psm, PSM_CHROOT_OUT);
+}
diff --git a/lib/psm.h b/lib/psm.h
index 968178b..90f1419 100644
--- a/lib/psm.h
+++ b/lib/psm.h
@@ -233,6 +233,11 @@ int psmStage(PSM_t psm, pkgStage stage)
 	/*@modifies psm, rpmGlobalMacroContext,
 		fileSystem, internalState @*/;
 
+/* ALT: hack to implement file triggers */
+void psmTriggerAdded(PSM_t psm);
+void psmTriggerRemoved(PSM_t psm);
+void psmTriggerPosttrans(PSM_t psm);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/transaction.c b/lib/transaction.c
index 2073882..ade1c46 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -2068,6 +2068,9 @@ assert(alp == fi->ap);
 		    ourrc++;
 		    lastFailed = i;
 		}
+		else {
+		    psmTriggerAdded(psm);
+		}
 		fi->h = headerFree(fi->h);
 		if (hsave) {
 		    fi->h = headerLink(hsave);
@@ -2094,11 +2097,18 @@ assert(alp == fi->ap);
 
 	    if (psmStage(psm, PSM_PKGERASE))
 		ourrc++;
+	    else {
+		psmTriggerRemoved(psm);
+	    }
 
 	    break;
 	}
 	(void) rpmdbSync(ts->rpmdb);
     }
+
+    if (ourrc == 0)
+	psmTriggerPosttrans(psm);
+
     tsi = tsFreeIterator(tsi);
 
     ts->flList = freeFl(ts, ts->flList);
diff --git a/rpm-4_0.spec b/rpm-4_0.spec
index 46c08b8..435831f 100644
--- a/rpm-4_0.spec
+++ b/rpm-4_0.spec
@@ -291,6 +291,7 @@ for dbi in \
 do
     touch "%buildroot%_localstatedir/%name/$dbi"
 done
+touch %buildroot%_localstatedir/%name/files-awaiting-filetriggers
 
 # Prepare documentation.
 bzip2 -9 CHANGES ||:
@@ -444,6 +445,7 @@ fi
 %rpmdbattr %_localstatedir/%name/Sigmd5
 %rpmdbattr %_localstatedir/%name/Sha1header
 %rpmdbattr %_localstatedir/%name/Triggername
+%rpmdbattr %_localstatedir/%name/files-awaiting-filetriggers
 
 /bin/rpm
 %_bindir/rpm
@@ -465,6 +467,8 @@ fi
 %_prefix/lib/rpmpopt
 %_prefix/lib/rpmrc
 
+%rpmattr %_rpmlibdir/posttrans-filetriggers
+
 %rpmattr %_rpmlibdir/functions
 %rpmattr %_rpmlibdir/find-package
 %rpmdatattr %_rpmlibdir/.provides.sh
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 6d5a5c1..b9900ba 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -3,6 +3,7 @@
 AUTOMAKE_OPTIONS = 1.4 foreign
 
 EXTRA_DIST = \
+	posttrans-filetriggers \
 	functions find-package .provides.sh \
 	find-scriptlet-requires \
 	brp-adjust_libraries brp-alt brp-bytecompile_python \
@@ -32,6 +33,7 @@ all:
 configdir = ${prefix}/lib/rpm
 config_DATA = .provides.sh 0common-files.req.list
 config_SCRIPTS = \
+	posttrans-filetriggers \
 	functions find-package \
 	find-scriptlet-requires \
 	brp-adjust_libraries brp-alt brp-bytecompile_python \
diff --git a/scripts/posttrans-filetriggers.in b/scripts/posttrans-filetriggers.in
new file mode 100755
index 0000000..1f80c51
--- /dev/null
+++ b/scripts/posttrans-filetriggers.in
@@ -0,0 +1,32 @@
+#!/bin/sh -efu
+#
+# File triggers are run at the end of successful transaction.
+#
+# Copyright (C) 2008  Alexey Tourbin <at@altlinux.org>
+#
+# Vaguely based on filetriggers.patch from Mandriva Linux.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+filelist=$1
+shift
+
+RC=0
+
+if [ -s "$filelist" ]; then
+	LC_ALL=C sort -u -o "$filelist" "$filelist"
+	set +f
+	for filetrigger in @RPMCONFIGDIR@/*.filetrigger; do
+		[ -x "$filetrigger" ] || continue
+		"$filetrigger" <"$filelist" ||
+		{
+			echo >&2 "$filetrigger failed"
+			RC=1
+		}
+	done
+fi
+
+exit $RC

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

             reply	other threads:[~2008-09-08  9:51 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-08  9:51 Alexey Tourbin [this message]
2008-09-08 12:07 ` Igor Vlasenko
2008-09-08 13:49 ` [devel] libgtk+2 Dmitry V. Levin
2008-09-08 13:55   ` Alexey Rusakov
2008-09-08 14:18   ` Yuri N. Sedunov
2008-09-08 14:23     ` Dmitry V. Levin
2008-09-08 14:42       ` Yuri N. Sedunov
2008-09-08 14:46         ` Dmitry V. Levin
2008-09-08 15:15           ` Yuri N. Sedunov
2008-09-08 15:21             ` Mikhail Gusarov
2008-09-08 15:24             ` Andrey Rahmatullin
2008-09-08 15:26             ` Alexey Rusakov
2008-09-08 15:41               ` Yuri N. Sedunov
2008-09-08 15:46                 ` Dmitry V. Levin
2008-09-08 15:54                   ` Yuri N. Sedunov
2008-09-09 10:05                     ` Sergey V Turchin
2008-09-08 15:27             ` Dmitry V. Levin
2008-09-11 19:25   ` [devel] /etc/ld.so.cache Alexey Tourbin
2008-09-11 19:58     ` Dmitry V. Levin
2008-09-11 20:16       ` Alexey Tourbin
2008-09-11 20:20         ` Dmitry V. Levin
2008-09-11 20:38           ` Alexey Tourbin
2008-09-11 20:48             ` Alexey Tourbin
2008-09-11 20:53               ` Dmitry V. Levin
2008-09-15  7:11                 ` Alexey Tourbin
2008-09-15 10:05                   ` Dmitry V. Levin
2008-09-19  7:02                     ` Alexey Tourbin
2008-10-06  7:04                   ` Alexey Tourbin
2008-09-11 20:50             ` Dmitry V. Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080908095106.GS6477@altlinux.org \
    --to=at@altlinux.ru \
    --cc=devel@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git