module-updater.pl 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. # Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
  2. # This program is free software: you can redistribute it and/or modify it under
  3. # the terms of the GNU General Public License as published by the Free Software
  4. # Foundation, either version 3 of the License, or (at your option) any later
  5. # version.
  6. #
  7. # This program is distributed in the hope that it will be useful, but WITHOUT
  8. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. #
  11. # You should have received a copy of the GNU General Public License along with
  12. # this program. If not, see <http://www.gnu.org/licenses/>.
  13. use strict;
  14. use v5.10;
  15. use File::Basename;
  16. use File::Copy;
  17. AddModuleDescription('module-updater.pl', 'Module Updater Extension');
  18. our ($q, %Action, @MyAdminCode, $TempDir, $ModuleDir);
  19. our $OddmuseModulesUrl = 'http://git.savannah.gnu.org/cgit/oddmuse.git/plain/modules/';
  20. push(@MyAdminCode, \&ModuleUpdaterMenu);
  21. $Action{updatemodules} = \&ModuleUpdaterAction;
  22. sub ModuleUpdaterMenu {
  23. return unless UserIsAdmin();
  24. my ($id, $menuref) = @_;
  25. push(@$menuref, ScriptLink('action=updatemodules', T('Update modules'), 'moduleupdater'));
  26. }
  27. sub ModuleUpdaterAction {
  28. UserIsAdminOrError();
  29. RequestLockOrError();
  30. print GetHeader('', T('Module Updater'), '', 'nocache');
  31. if (GetParam('ok')) {
  32. ModuleUpdaterApply();
  33. } else {
  34. Unlink(Glob("$TempDir/*.p[ml]")); # XXX is it correct to use $TempDir for such stuff? What if something else puts .pm files there?
  35. for (Glob("$ModuleDir/*.p[ml]")) {
  36. my $curModule = fileparse($_);
  37. ProcessModule($curModule);
  38. }
  39. print $q->br();
  40. print GetFormStart(undef, 'get');
  41. print GetHiddenValue('action', 'updatemodules');
  42. print $q->submit(-name=>'ok', -value=>T('Looks good. Update modules now!'));
  43. print $q->end_form();
  44. }
  45. PrintFooter();
  46. ReleaseLock();
  47. }
  48. sub ModuleUpdaterApply {
  49. for (Glob("$TempDir/*.p[ml]")) {
  50. my $moduleName = fileparse($_);
  51. if (move($_, "$ModuleDir/$moduleName")) {
  52. print $q->strong("Module $moduleName updated successfully!"), $q->br();
  53. } else {
  54. print $q->strong("Unable to replace module $moduleName: $!"), $q->br();
  55. }
  56. }
  57. Unlink(Glob("$TempDir/*.p[ml]")); # XXX same as above
  58. print $q->br(), $q->strong('Done!');
  59. }
  60. sub ProcessModule {
  61. my $module = shift;
  62. CreateDir($TempDir);
  63. print $q->hr();
  64. print $q->strong("Diffing $module ..."), $q->br();
  65. my $moduleData = GetRaw("$OddmuseModulesUrl/$module");
  66. if (not $moduleData) {
  67. print $q->strong('There was an error downloading this module.'
  68. . ' If this is your own module, please contribute it to Oddmuse!'), $q->br();
  69. return;
  70. }
  71. my $file = "$TempDir/$module";
  72. open my $fh, ">:utf8", encode_utf8($file) or die("Could not open file $TempDir/$module: $!");
  73. print $fh $moduleData;
  74. close $fh;
  75. my $diff = DoModuleDiff("$ModuleDir/$module", "$TempDir/$module");
  76. if (not $diff) {
  77. print $q->strong('This module is up to date, there is no need to update it.'), $q->br();
  78. Unlink("$TempDir/$module");
  79. return;
  80. }
  81. print $q->strong('There is a newer version of this module. Here is a diff:'), $q->br();
  82. $diff = QuoteHtml($diff);
  83. $diff =~ tr/\r//d; # TODO is this required? # probably not # but maybe it is there to fix problems with dos newlines?
  84. for (split /\n/, $diff) {
  85. my ($type) = /(.)/;
  86. if ($type =~ /[+-]/) {
  87. my $class = $type eq '+' ? 'updaternew' : 'updaterold';
  88. print $q->span({-class => $class}, $q->code($_));
  89. } else {
  90. print $q->span($q->code($_));
  91. }
  92. print $q->br();
  93. }
  94. }
  95. sub DoModuleDiff {
  96. my $diff = decode_utf8(`diff -U 3 -- \Q$_[0]\E \Q$_[1]\E`);
  97. return $diff;
  98. }