Re: Where to point CommitFestOpen? - Mailing list pgsql-hackers
From | Jens-Wolfhard Schicke |
---|---|
Subject | Re: Where to point CommitFestOpen? |
Date | |
Msg-id | 490EC517.3040407@gmx.de Whole thread Raw |
In response to | Re: Where to point CommitFestOpen? (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-hackers |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Tom Lane wrote: > Somehow, "prevent infinite loops" doesn't seem like justification for > "refuse to deal with a situation that the software creates automatically". > They ought to be willing to burrow more than one level ... see any Unix > kernel's treatment of symlinks for behavior that has actually stood the > test of usability over time. Having faced similar problems in another wiki some month ago, I wrote the attached script to automate some tasks in a wiki. Maybe it will be of use. Unfortunately I wrote it for a german wiki, some of the special pages are named differently. Hence to use it in the Postgres-Wiki, something needs to be done probably. (Not much though). In particular it includes a function to "execute" a redirect in all pages referencing a redirect page, i.e. change the links within all incoming pages. Regards, Jens-W. Schicke -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkkOxRYACgkQzhchXT4RR5CJQQCghUUCLO+e0QtZOTD7sALCPv0p masAn1FfB786qM9QIbQXlOokK+4R7x7I =HWF8 -----END PGP SIGNATURE----- #!/usr/bin/perl use strict; use warnings; use MediaWiki; use Data::Dumper; use LWP; use LWP::UserAgent; my $wiki = MediaWiki->new() or die "Wiki init failed"; my $lwp = LWP::UserAgent->new(); $lwp->agent("Drahflow's Wiki Bot"); my $WIKINAME = $ARGV[0] or die "usage: ./bot.pl <Wiki>"; my $conf; if($WIKINAME eq "AK") { $conf = { 'wiki' => { 'host' => 'wiki.vorratsdatenspeicherung.de', 'path' => '/' }, 'bot' => { 'user' => 'Drahflow\'s Bot', 'pass' => 'secret' }, }; } else { die "Unknown wiki: $WIKINAME"; } $wiki->setup($conf); $wiki->login(); while(my $command = <STDIN>) { chomp $command; last if($command eq "q" or $command eq "quit"); eval { dumpContent($1) if($command =~ /^DUMP ([^|]*)$/); execTest() if($command eq 'TEST'); cleanupRedirect($1, $2) if($command =~ /^CREDIR ([^|]*)\|?(del)?$/); checkout($1) if($command =~ /^MVOUT ([^|]*)$/); checkin($1, $2) if($command =~ /^MVIN ([^|]*)\|?([^|]*)$/); copyout($1) if($command =~ /^GET ([^|]*)$/); checkToDoUsage() if($command =~ /^QTODO$/); checkLanguageSync() if($command =~ /^QLANG$/); moveCategory($1, $2) if($command =~ /^CMV ([^|]*)\|?([^|]*)$/); addCategories($1, $2) if($command =~ /^CADD (.*)\|\|(.*)$/); }; print STDERR $@ if $@; } $wiki->logout(); sub loadSure { my ($name, $mode) = @_; die "no mode given" unless $mode; my $page = $wiki->get($name, $mode); unless($page and $page->load()) { die "could not load $name"; } print "Page $name loaded.\n"; return $page; } sub loadCategorySure { my ($name) = @_; unless($name =~ /Kategorie:|Category:/) { die "category name must be given with prefix"; } my $req = HTTP::Request->new( 'GET' => 'http://' . $conf->{'wiki'}->{'host'} . '/' . $name); my $res = $lwp->request($req); if(not $res->is_success()) { die "could not load $name"; } my ($subcatsPart) = $res->content() =~ /\n<h2>Unterkategorien(.*?)\n<h2/s; my ($articlesPart) = $res->content() =~ /\n<h2>Seiten in der Kategorie(.*?)\nVon/s; my $subcats = []; my $articles = []; while(defined $subcatsPart and $subcatsPart =~ s/.*?<a href="\/([^"]+)" title="([^"]+)">//) { push @$subcats, $2; } while(defined $articlesPart and $articlesPart =~ s/.*?<a href="\/([^"]+)" title="([^"]+)">//) { push @$articles, $2; } print "Category $name loaded.\n"; return $articles, $subcats; } sub saveSure { my ($page, $summary, $minor) = @_; if($page->{'title'} =~ /Ortsgruppe/) { askConfirmation("Page " . $page->{'title'} . " looks like it should be left alone"); } die "no summary given" unless $summary; if($minor) { $page->{'minor'} = 1; } else { $page->{'minor'} = 0; } $page->{'summary'} = $summary; unless($page->save()) { die "could not save " . $page->{'title'}; } print "Page " . $page->{'title'} . " saved.\n"; return $page; } sub askConfirmation { my ($message) = @_; while(1) { print "==> $message, continue [N/y]\n"; my $answer = <STDIN>; chomp $answer; if($answer eq '' or $answer eq 'n') { die "User confirmation failed."; } if($answer eq 'y') { last; } } } sub dumpContent { my ($name) = @_; die "no name given" unless $name; my $page = loadSure($name, "r"); my $text = $page->content(); print Dumper($text); } sub execTest { my $page = loadSure('Benutzer:Drahflow/Sandkasten', "rw"); my $text = $page->content(); print Dumper($text); $page->{'content'} .= 'Minimaler Testlauf'; saveSure($page, 'Testing [[Benutzer:Drahflow]]\'s Bot'); } sub cleanupRedirect { my ($name, $del) = @_; die "no name given" unless $name; my @incoming; my $page = loadSure("Spezial:Linkliste/$name", "r"); my $content = $page->content(); while($content =~ s!<a href="/([^"]+)" title="([^"]+)">\2</a>[^<]*<span class="mw-whatlinkshere-tools">!!) { my ($url, $title) = ($1, $2); push @incoming, $title; } print "Incoming links:\n"; print Dumper(\@incoming); $page = loadSure($name, "r"); $content = $page->content(); $content =~ m!#redirect ?\[\[([^\]]+)\]\]!i or die "could not find redirect"; my $redirect = $1; print "Redirect to: $redirect\n"; foreach my $in (@incoming) { $page = loadSure($in, "rw"); my $any = 0; my $mask = $name; $mask =~ s/ /[ _]/g; while($page->{'content'} =~ m!\[\[$mask(#[^ ]*)?( ?\|([^\]]+))?\]\]!s) { my ($anchor, undef, $display) = ($1, $2, $3); if(not defined $anchor) { $anchor = ''; } if(not defined $display) { $display = $name; } print "Displayname: $display\n"; $page->{'content'} =~ s!\[\[$mask(#[^ ]*)?( ?(\|[^\]]+)?)\]\]![[$redirect$anchor\|$display]]!; print "Link on $in fixed.\n"; ++$any; } die "incoming link not found" if(not $any); askConfirmation("Page $in will be saved"); saveSure($page, "Weiterleitungs-Cleanup, Link von $name auf $redirect verbogen"); } if($del) { $page = loadSure($name, "rw"); $content = $page->content(); if($content =~ m!^#redirect ?\[\[$redirect\]\]$!si) { $page->{'content'} .= "\n{{Vorlage:Drahflow/Löschen/Weiterleitung}}"; print "Inserted deletion remark.\n"; } askConfirmation("Page $name will be saved"); saveSure($page, "Weiterleitungs-Cleanup, Weiterleitung zum Löschen eingetragen"); } print "Done.\n"; } sub sanitizeFilename { my ($name) = @_; $name =~ s/-/--/g; $name =~ s!/!-+!g; return "checkout/$name"; } sub checkout { my ($name) = @_; die "no name given" unless $name; my $page = loadSure($name, "rw"); if($page->content() =~ /{{ *InArbeit/ or $page->content() =~ /{{ *Vorlage: *InArbeit/) { askConfirmation("Page $name is tagged with {{Vorlage:InArbeit}}"); } my $origContent = $page->{'content'}; $page->{'content'} = "{{Vorlage:InArbeit|[[Benutzer:Drahflow]]}}\n" . $page->{'content'}; saveSure($page, "{{:Vorlage:InArbeit}} gesetzt", 1); my $filename = sanitizeFilename($name); open PAGE, '>', $filename or die "cannot open $filename: $!"; print PAGE $origContent; close PAGE; print "Done.\n"; } sub copyout { my ($name) = @_; die "no name given" unless $name; my $page = loadSure($name, "rw"); my $filename = sanitizeFilename($name); open PAGE, '>', $filename or die "cannot open $filename: $!"; print PAGE $page->content(); close PAGE; print "Done.\n"; } sub checkin { my ($name, $reason) = @_; die "no name given" unless $name; die "no reason given" unless $reason; my $filename = sanitizeFilename($name); open PAGE, '<', $filename or die "cannot open $filename: $!"; my $origContent = join('', <PAGE>); close PAGE; my $page = loadSure($name, "rw"); if($page->content() !~ /^{{Vorlage:InArbeit|\[\[Benutzer:Drahflow\]\]}}/s) { askConfirmation("Page $name is not tagged as being edited by you"); } $page->{'content'} = $origContent; saveSure($page, $reason); unlink $filename; print "Done.\n"; } sub getTemplateUsers { my ($name) = @_; die "no template name given" unless $name; my $page = loadSure("Spezial:Linkliste/$name", "r"); my @users; my $content = $page->content(); while($content =~ s!<a href="/([^"]+)" title="([^"]+)">\2</a> *\(Vorlageneinbindung\) *<span class="mw-whatlinkshere-tools">!!){ my ($url, $title) = ($1, $2); push @users, $title; } return @users; } sub checkToDoUsage { my @users = getTemplateUsers("Vorlage:ToDo"); my @problems; foreach my $user (@users) { my $page = loadSure($user, "r"); if($page->content() =~ /{{Vorlage: *ToDo/) { push @problems, $user; } } foreach my $user (@problems) { print "Problematic usage: $user\n"; } print "Done.\n"; } sub moveCategory { my ($from, $to) = @_; die "no from category given" unless $from; die "no to category given" unless $to; my ($articles, $subcats) = loadCategorySure($from); my @problems; foreach my $entry (@$articles, @$subcats) { my $page = loadSure($entry, "rw"); my $success = 0; if($page->{'content'} =~ /\[\[$to\]\]/) { if($page->{'content'} =~ s/\[\[$from\]\]//) { $success = 1; } } else { if($page->{'content'} =~ s/\[\[$from\]\]/[[$to]]/) { $success = 1; } } if($success) { saveSure($page, "Kategorie-Umbenennung: von $from nach $to"); } else { push @problems, $entry; } } foreach my $entry (@problems) { print "Problematic usage: $entry\n"; } print "Done.\n"; } sub checkLanguageSync { my %users = map { ($_, $_) } getTemplateUsers("Vorlage:Mehrsprachig"); my @problems; while(%users) { my ($first) = keys %users; my $page = loadSure($first, "r"); unless($page->content() =~ /{{(Vorlage:)? *Mehrsprachig\b(.*)}}/s) { delete $users{$first}; push @problems, "Could not find template call: $first"; next; } my $parameters = $2; unless($parameters =~ /\bsynchronisiert *= *1/) { delete $users{$first}; next; } my @otherPages; push @otherPages, $1 if($parameters =~ /\bde *= *([^|{}]*)/s); push @otherPages, $1 if($parameters =~ /\ben *= *([^|{}]*)/s); @otherPages = grep { $_ ne $first } map { chomp; $_ } @otherPages; if(@otherPages < 1) { delete $users{$first}; push @problems, "Synchronization group of less than 2 on $first"; next; } OTHERS: foreach my $other (@otherPages) { my @firstLines = split /\n/, $page->content(); my @otherLines = split /\n/, loadSure($other, "r")->content(); if(@firstLines != @otherLines) { push @problems, "Line counts differ between $first and $other"; last OTHERS; } @firstLines = map { length($_)? 1: 0; } @firstLines; @otherLines = map { length($_)? 1: 0; } @otherLines; for(my $i = 0; $i < @firstLines; ++$i) { if($firstLines[$i] ne $otherLines[$i]) { push @problems, "Line " . ($i + 1) . " differs between $first and $other"; last OTHERS; } } } delete $users{$first}; foreach my $page (@otherPages) { delete $users{$page}; } } foreach my $entry (@problems) { print "$entry\n"; } print "Done.\n"; } sub addCategories { my ($categories, $names) = @_; my @categories = split(/\|/, $categories); my @names = split(/\|/, $names); die "no categories given" unless @categories; die "no pages given" unless @names; my %pagesInCat; foreach my $cat (@categories) { my $correctPages = loadCategorySure($cat); $pagesInCat{$cat} = $correctPages; } foreach my $name (@names) { my $page = loadSure($name, "rw"); my $changes = 0; foreach my $cat (@categories) { next if(grep { $_ eq $name } @{$pagesInCat{$cat}}); $page->{'content'} .= "\n[[$cat]]"; print "$cat added.\n"; $changes = 1; } if($changes) { saveSure($page, "Kategorie hinzugefügt"); } } print "Done.\n"; } #TODO: Something within a directory which is also a name of a category should # belong to said category #TODO: Nothing should belong to a category and also directly to some category # above it. #TODO: Everything should have a category #TODO: Categories should not be cyclic
Attachment
pgsql-hackers by date: