Browse Source

update-alternatives: rewritten in C

update-alternative has been rewritten as a mostly standalone C program.
It has thus been moved to utils/ instead of scripts/ together with its
README and its test suite.

This rewrite is based on some initial conversion work done by Guillem
Jover <guillem@debian.org>.

The program now logs to /var/log/alternatives.log instead of dpkg.log.
The logrotate file has been updated to deal with that file too.
Raphaël Hertzog 14 years ago
parent
commit
cab5af04fa

+ 3 - 0
debian/changelog

@@ -28,6 +28,9 @@ dpkg (1.15.8) UNRELEASED; urgency=low
     properly when <lastversion> is not given (or is empty). Closes: #582819
   * Small fix in dpkg-gensymbols' handling of tags. Closes: #583656
     Thanks to Michael Tautschnig <mt@debian.org> for the report and the fix.
+  * update-alternatives has been rewritten in C, the only feature change
+    should be that it uses its own logfile /var/log/alternatives.log (rotated
+    like dpkg.log).
 
   [ Guillem Jover ]
   * Require gettext 0.18:

+ 9 - 0
debian/dpkg.logrotate

@@ -7,3 +7,12 @@
 	notifempty
 	create 644 root root
 }
+/var/log/alternatives.log {
+	monthly
+	rotate 12
+	compress
+	delaycompress
+	missingok
+	notifempty
+	create 644 root root
+}

+ 0 - 1
scripts/.gitignore

@@ -17,5 +17,4 @@ dpkg-shlibdeps
 dpkg-source
 dpkg-statoverride
 dpkg-vendor
-update-alternatives
 t.tmp

+ 0 - 12
scripts/Makefile.am

@@ -22,10 +22,6 @@ bin_SCRIPTS = \
 	dpkg-source \
 	dpkg-vendor
 
-if WITH_UPDATE_ALTERNATIVES
-bin_SCRIPTS += update-alternatives
-endif
-
 changelogdir = $(pkglibdir)/parsechangelog
 changelog_SCRIPTS = \
 	changelog/debian
@@ -50,7 +46,6 @@ EXTRA_DIST = \
 	dpkg-source.pl \
 	dpkg-divert.pl \
 	dpkg-vendor.pl \
-	update-alternatives.pl \
 	changelog/debian.pl \
 	$(test_cases) \
 	$(test_data)
@@ -151,11 +146,6 @@ if BUILD_POD_DOC
 		rm -f $(DESTDIR)$(man3dir)/$$name.3; \
 	done
 endif
-if WITH_UPDATE_ALTERNATIVES
-	$(mkdir_p) $(DESTDIR)$(sysconfdir)/alternatives
-	$(mkdir_p) $(DESTDIR)$(admindir)/alternatives
-	$(INSTALL_DATA) $(srcdir)/README.alternatives $(DESTDIR)$(sysconfdir)/alternatives/README
-endif
 
 # Ideally we'd use 'sed -i', but unfortunately that's not portable.
 install-data-hook:
@@ -171,7 +161,6 @@ if BUILD_POD_DOC
 	    rm -f $(DESTDIR)$(man3dir)/`echo $$module | sed -e 's|/|::|g' -e 's/\.pm$$/.3/'`; \
 	done
 endif
-	rm -f $(DESTDIR)$(sysconfdir)/alternatives/README
 
 TEST_VERBOSE= 0
 
@@ -191,7 +180,6 @@ test_cases = \
 	t/750_Dpkg_Substvars.t \
 	t/800_Dpkg_IPC.t \
 	t/850_Dpkg_Compression.t \
-	t/900_update_alternatives.t \
 	t/910_merge_changelogs.t
 
 check_DATA = \

File diff suppressed because it is too large
+ 0 - 1139
scripts/update-alternatives.pl


+ 2 - 0
utils/.gitignore

@@ -1,2 +1,4 @@
 start-stop-daemon
+update-alternatives
 dpkg-install-info
+t.tmp

+ 40 - 0
utils/Makefile.am

@@ -2,11 +2,27 @@
 
 localedir = $(datadir)/locale
 AM_CPPFLAGS = \
+	-DADMINDIR=\"$(admindir)\" \
 	-DLOCALEDIR=\"$(localedir)\" \
+	-DLOGDIR=\"$(logdir)\" \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	-idirafter $(top_srcdir)/lib/compat \
 	-I$(top_builddir) \
 	-I$(top_srcdir)/lib
 
+bin_PROGRAMS =
+
+if WITH_UPDATE_ALTERNATIVES
+bin_PROGRAMS += update-alternatives
+endif
+
+update_alternatives_SOURCES = \
+	update-alternatives.c
+
+update_alternatives_LDADD = \
+	../lib/compat/libcompat.a \
+	$(UA_LIBS)
+
 sbin_PROGRAMS =
 
 if WITH_START_STOP_DAEMON
@@ -32,8 +48,32 @@ endif
 
 transform = s/dpkg-install-info/install-info/; $(program_transform_name)
 
+install-data-local:
+if WITH_UPDATE_ALTERNATIVES
+	$(mkdir_p) $(DESTDIR)$(sysconfdir)/alternatives
+	$(mkdir_p) $(DESTDIR)$(admindir)/alternatives
+	$(INSTALL_DATA) $(srcdir)/README.alternatives $(DESTDIR)$(sysconfdir)/alternatives/README
+endif
+
 uninstall-local:
+	rm -f $(DESTDIR)$(sysconfdir)/alternatives/README
 if WITH_INSTALL_INFO
 	rm -f $(DESTDIR)$(sbindir)/install-info
 endif
 
+TEST_VERBOSE = 0
+test_tmpdir = t.tmp
+test_cases = \
+	t/100_update_alternatives.t
+
+clean-local:
+	rm -fr $(test_tmpdir)
+
+check: $(test_cases)
+	$(mkdir_p) $(test_tmpdir)
+	PATH="$(top_builddir)/src:$(top_builddir)/scripts:$(top_builddir)/utils:$(PATH)" \
+	  srcdir=$(srcdir) builddir=$(builddir) DPKG_DATADIR=$(top_srcdir) \
+	  PERL5LIB=$(top_srcdir)/scripts \
+	  $(PERL) -MExtUtils::Command::MM \
+		  -e "test_harness($(TEST_VERBOSE), '.')" \
+		  $(addprefix $(srcdir)/,$(test_cases))

scripts/README.alternatives → utils/README.alternatives


+ 26 - 13
scripts/t/900_update_alternatives.t

@@ -25,10 +25,14 @@ my $tmpdir = 't.tmp/900_update_alternatives';
 my $admindir = File::Spec->rel2abs("$tmpdir/admindir"),
 my $altdir = File::Spec->rel2abs("$tmpdir/alternatives");
 my $bindir = File::Spec->rel2abs("$tmpdir/bin");
-# XXX: switch to version without .pl
-my @ua = ("$srcdir/update-alternatives.pl", "--log", "/dev/null",
+my @ua = ("$ENV{builddir}/update-alternatives", "--log", "/dev/null",
           "--quiet", "--admindir", "$admindir", "--altdir", "$altdir");
 
+if (! -x "$ENV{builddir}/update-alternatives") {
+    plan skip_all => "update-alternatives not available";
+    exit(0);
+}
+
 my $main_link = "$bindir/generic-test";
 my $main_name = "generic-test";
 my @choices = (
@@ -67,7 +71,7 @@ my @choices = (
 );
 my $nb_slaves = 2;
 plan tests => (4 * ($nb_slaves + 1) + 2) * 24 # number of check_choices
-		+ 63;			      # rest
+		+ 64;			      # rest
 
 sub cleanup {
     system("rm -rf $tmpdir && mkdir -p $admindir && mkdir -p $altdir");
@@ -78,10 +82,14 @@ sub call_ua {
     my ($params, %opts) = @_;
     spawn("exec" => [ @ua, @$params ], nocheck => 1,
 	  wait_child => 1, env => { LC_ALL => "C" }, %opts);
+    my $test_id = "";
+    $test_id = "$opts{test_id}: " if defined $opts{test_id};
     if ($opts{"expect_failure"}) {
-	ok($? != 0, "update-alternatives @$params did not fail.");
+	ok($? != 0, "${test_id}update-alternatives @$params should fail.") or
+	    diag("Did not fail as expected: @ua @$params");
     } else {
-	ok($? == 0, "update-alternatives @$params failed.");
+	ok($? == 0, "${test_id}update-alternatives @$params should work.") or
+	    diag("Did not succeed as expected: @ua @$params");
     }
 }
 
@@ -181,7 +189,7 @@ sub check_choice {
     my $output;
     if (defined $id) {
 	# Check status
-	call_ua([ "--query", "$main_name" ], to_string => \$output);
+	call_ua([ "--query", "$main_name" ], to_string => \$output, test_id => $msg);
 	$output =~ /^Status: (.*)$/im;
 	is($1, $mode, "$msg: status is not $mode.");
 	# Check links
@@ -191,7 +199,7 @@ sub check_choice {
 	check_slaves($id, $msg);
     } else {
 	call_ua([ "--query", "$main_name" ], error_to_string => \$output,
-	        expect_failure => 1);
+	        expect_failure => 1, test_id => $msg);
 	ok($output =~ /no alternatives/, "$msg: bad error message for --query.");
 	# Check that all links have disappeared
 	check_no_link("$altdir/$main_name", $msg);
@@ -211,24 +219,25 @@ install_choice(2); # 2 is lower prio, stays at 1
 check_choice(1, "auto", "initial install 2");
 install_choice(0); # 0 is higher priority
 check_choice(0, "auto", "initial install 3");
+
 # manual change with --set-selections
 my $input = "doesntexist auto /bin/date\ngeneric-test manual /bin/false\n";
 my $output = "";
 call_ua(["--set-selections"], from_string => \$input,
-        to_string => \$output);
+        to_string => \$output, test_id => "manual update with --set-selections");
 check_choice(1, "manual", "manual update with --set-selections");
 $input = "generic-test auto /bin/true\n";
 call_ua(["--set-selections"], from_string => \$input,
-        to_string => \$output);
+        to_string => \$output, test_id => "auto update with --set-selections");
 check_choice(0, "auto", "auto update with --set-selections");
 # manual change with set
-set_choice(2);
+set_choice(2, test_id => "manual update with --set");
 check_choice(2, "manual", "manual update with --set"); # test #388313
-remove_choice(2);
+remove_choice(2, test_id => "remove manual, back to auto");
 check_choice(0, "auto", "remove manual, back to auto");
-remove_choice(0);
+remove_choice(0, test_id => "remove best");
 check_choice(1, "auto", "remove best");
-remove_choice(1);
+remove_choice(1, test_id => "no alternative left");
 check_choice(undef, "", "no alternative left");
 # single choice in manual mode, to be removed
 install_choice(1);
@@ -303,6 +312,10 @@ call_ua(["--install", "$bindir/testmaster", "slave1", "/bin/date", "10"],
 call_ua(["--install", "$bindir/testmaster", "testmaster", "/bin/date", "10",
 	 "--slave", "$bindir/testslave", "generic-test", "/bin/true" ],
 	expect_failure => 1, to_file => "/dev/null", error_to_file => "/dev/null");
+# try to reuse master link in slave
+call_ua(["--install", "$bindir/testmaster", "testmaster", "/bin/date", "10",
+	 "--slave", "$bindir/testmaster", "testslave", "/bin/true" ],
+	expect_failure => 1, to_file => "/dev/null", error_to_file => "/dev/null");
 # try to reuse links in master alternative
 call_ua(["--install", "$bindir/slave1", "testmaster", "/bin/date", "10"],
         expect_failure => 1, to_file => "/dev/null", error_to_file => "/dev/null");

File diff suppressed because it is too large
+ 2441 - 0
utils/update-alternatives.c