From 6fcb0fc5e2c986b4191077ebc2cf588706c4b535 Mon Sep 17 00:00:00 2001 From: mfr69bs <> Date: Sat, 23 Feb 2013 00:15:07 +0000 Subject: [PATCH] added support for third-party packages to update.pm git-svn-id: https://svn.fhem.de/fhem/trunk@2788 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 5 +- fhem/FHEM/98_update.pm | 498 ++++++++++++++++++++------- fhem/docs/LIESMICH.update-thirdparty | 145 ++++++++ 3 files changed, 531 insertions(+), 117 deletions(-) create mode 100644 fhem/docs/LIESMICH.update-thirdparty diff --git a/fhem/CHANGED b/fhem/CHANGED index 4ff701287..1bd3bdec3 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -4,8 +4,8 @@ - feature: added new Javascript Frontend based on ExtJS (by Johannes) - feature: new Modules 30_HUEDevice and 31_HUEBridge for phillips hue and smartlink devices (by justme1968) - - change: SYSSTAT: allow remote monitoring by ssh - - change: SYSSTAT: allow less frequent updates for diskusage + - change: SYSSTAT: allow remote monitoring by ssh + - change: SYSSTAT: allow less frequent updates for diskusage - feature: new Module 32_SYSSTAT to monitor system load and disk usage on linux FHEM hosts (by justme1968) - feature: new Module 73_PRESENCE to make automatic presence detection of @@ -89,6 +89,7 @@ smallscreen/touchpad moved to stylesheetPrefix, menuEntries added, Extend devStateIcon, js setting of attr values in detail screen, live slider update in detail and room view + - feature: added support for third-party packages to 98_update.pm (M. Fischer) - 2012-10-28 (5.3) - feature: added functions trim, ltrim, rtrim, UntoggleDirect, diff --git a/fhem/FHEM/98_update.pm b/fhem/FHEM/98_update.pm index a10a3d841..224ac20d5 100644 --- a/fhem/FHEM/98_update.pm +++ b/fhem/FHEM/98_update.pm @@ -1,10 +1,26 @@ ################################################################ # $Id$ # vim: ts=2:et -# +################################################################ +# # (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de) # All rights reserved # +# This script 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. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# A copy is found in the textfile GPL.txt and important notices to the license +# from the author is found in LICENSE.txt distributed with these scripts. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# ################################################################ package main; use strict; @@ -13,18 +29,17 @@ use HttpUtils; use File::Copy qw(cp mv); sub CommandUpdate($$); -sub update_CheckFhemRelease($$); -sub update_CheckUpdates($$$$); +sub update_CheckFhemRelease($$$); +sub update_CheckNotice($$$); +sub update_CheckUpdates($$$$$); sub update_CleanUpLocalFiles($$$); sub update_DoUpdate(@); -sub update_DoHousekeeping($); -sub update_GetRemoteFiles($$$); -sub update_ListChanges($); +sub update_DoHousekeeping($$); +sub update_GetRemoteFiles($$$$); +sub update_ListChanges($$$); sub update_MakeDirectory($); sub update_ParseControlFile($$$$); -sub update_WriteLocalControlFile($$$); - -my $BRANCH; +sub update_WriteLocalControlFile($$$$); ######################################## @@ -62,7 +77,7 @@ CommandUpdate($$) my @args = split(/ +/,$param); # set default trunk - $BRANCH = (!defined($attr{global}{updatebranch}) ? $DISTRIB_BRANCH : uc($attr{global}{updatebranch})); + my $BRANCH = (!defined($attr{global}{updatebranch}) ? $DISTRIB_BRANCH : uc($attr{global}{updatebranch})); if ($BRANCH ne "STABLE" && $BRANCH ne "DEVELOPMENT") { $ret = "global attribute 'updatebranch': unknown keyword: '$BRANCH'. Keyword should be 'STABLE' or 'DEVELOPMENT'"; Log 1, "update $ret"; @@ -71,36 +86,71 @@ CommandUpdate($$) if (!defined($args[0])) { push(@args,$BRANCH); - } elsif (uc($args[0]) ne "STABLE" && uc($args[0]) ne "DEVELOPMENT") { + } elsif (uc($args[0]) ne "STABLE" && uc($args[0]) ne "DEVELOPMENT" && uc($args[0]) ne "THIRDPARTY") { unshift(@args,$BRANCH); - } elsif (uc($args[0]) eq "STABLE" || uc($args[0]) eq "DEVELOPMENT") { + } elsif (uc($args[0]) eq "STABLE" || uc($args[0]) eq "DEVELOPMENT" || uc($args[0]) eq "THIRDPARTY") { $args[0] = uc($args[0]); - $BRANCH = $args[0]; + $BRANCH = uc($args[0]); } - # set path for fhem.de - my $branch = lc($BRANCH); - $branch = "SVN" if ($BRANCH eq "DEVELOPMENT"); - $srcdir = $UPDATE{path}."/".lc($branch); - # check arguments - if (defined($args[1]) && $args[1] eq "?" || - (int(@args) > 3 && uc($args[1]) eq "HOUSEKEEPING") || - (int(@args) > 2 && uc($args[2]) ne "FORCE" && - (uc($args[1]) eq "CHECK" || - uc($args[1]) eq "FHEM" || - uc($args[1]) eq "FULL")) || - (int(@args) > 2 && - (uc($args[1]) ne "CHECK" && - uc($args[1]) ne "FHEM" && - uc($args[1]) ne "FULL" && - uc($args[1]) ne "HOUSEKEEPING"))) { - return "Usage: update [development|stable] [|check|fhem|full] [force]"; - } + if (defined($args[1]) && $args[1] eq "?") { + # return complete usage + $ret = "Usage:\n"; + $ret .= "=> FHEM update / check for updates:\n"; + $ret .= "\tupdate [development|stable] [] [force]\n"; + $ret .= "\tupdate [development|stable] check\n"; + $ret .= "\tupdate housekeeping\n"; + $ret .= "=> Third party package update / check for a package update:\n"; + $ret .= "\tupdate thirdparty [force]\n"; + $ret .= "\tupdate thirdparty check"; + return $ret; + + } elsif (int(@args) <= 2 && $BRANCH eq "THIRDPARTY") { + # missing arguments for third party package + $ret = "Usage:\n"; + $ret .= "\tupdate thirdparty [force]\n"; + $ret .= "\tupdate thirdparty check"; + return $ret; + + } elsif (int(@args) > 2) { + + if (grep (m/^HOUSEKEEPING$/i,@args)) { + return "Usage: update housekeeping"; + + } elsif (grep (m/^CHECK$/i,@args)) { + + if (($BRANCH eq "STABLE" || + $BRANCH eq "DEVELOPMENT") && + $BRANCH ne "THIRDPARTY" + ) { + return "Usage: update [development|stable] check"; + + } elsif ($BRANCH eq "THIRDPARTY" && + (uc($args[1]) !~ m/^HTTP:/ || + uc($args[3]) !~ "CHECK" || + int(@args) != 4) + ) { + return "Usage: update thirdparty check"; + } + + } elsif ($BRANCH eq "THIRDPARTY" && + (uc($args[1]) !~ m/^HTTP:/ || + (int(@args) == 4 && + uc($args[3]) ne "FORCE") || + int(@args) > 4) + ) { + return "Usage: update thirdparty [force]"; + + } elsif ($BRANCH ne "THIRDPARTY" && + (exists $UPDATE{uc($args[1])} && + (int(@args) == 3 && + uc($args[2]) ne "FORCE") || + int(@args) > 3) + ) { + return "Usage: update [development|stable] [force]"; + } - # check arguments for housekeeping - if (defined($args[1]) && uc($args[1]) eq "HOUSEKEEPING" && (int(@args) > 2 )) { - return "Usage: update housekeeping"; } # set default update @@ -109,30 +159,44 @@ CommandUpdate($$) (uc($args[1]) eq "FORCE") || uc($args[1]) eq "HOUSEKEEPING")) { $update = "FHEM"; + } elsif (exists $UPDATE{uc($args[1])}) { + $update = uc($args[1]); } else { $update = $args[1]; } - # force update - $force = 1 if (defined($args[1]) && uc($args[1]) eq "FORCE" || - defined($args[2]) && uc($args[2]) eq "FORCE"); + # build sourcedir for update + if ($BRANCH ne "THIRDPARTY") { + # set path for fhem.de + my $branch = lc($BRANCH); + $branch = "SVN" if ($BRANCH eq "DEVELOPMENT"); + $srcdir = $UPDATE{path}."/".lc($branch); + } else { + # set path for 3rd-party + $srcdir = $args[1]; + $update = $args[2]; + } - if (defined($args[1]) && uc($args[1]) eq "CHECK") { - $ret = update_ListChanges($srcdir); + # force update + $force = 1 if (grep (m/^FORCE$/i,@args)); + + if (defined($args[1]) && uc($args[1]) eq "CHECK" || + $BRANCH eq "THIRDPARTY" && defined($args[3]) && uc($args[3]) eq "CHECK") { + $ret = update_ListChanges($srcdir,$BRANCH,$update); } elsif (defined($args[1]) && uc($args[1]) eq "HOUSEKEEPING") { - $ret = update_DoHousekeeping($update); + $ret = update_DoHousekeeping($BRANCH,$update); $ret = "nothing to do..." if (!$ret); } else { my $unconfirmed; my $notice; - ($notice,$unconfirmed) = update_CheckNotice("before"); + ($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"before"); $ret .= $notice if(defined($notice)); return $ret if($unconfirmed); $ret .= update_DoUpdate($srcdir,$BRANCH,$update,$force,$cl); - ($notice,$unconfirmed) = update_CheckNotice("after"); + ($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"after"); $ret .= $notice if(defined($notice)); my $sendStatistics = AttrVal("global","sendStatistics",undef); - if(lc($sendStatistics) eq "onupdate") { + if(defined($sendStatistics) && lc($sendStatistics) eq "onupdate") { $ret .= "\n\n"; $ret .= AnalyzeCommandChain(undef, "fheminfo send"); } @@ -143,12 +207,13 @@ CommandUpdate($$) ######################################## sub -update_CheckNotice($) +update_CheckNotice($$$) { - my ($position) = shift; + my ($BRANCH,$update,$position) = @_; my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; my $noticeDir = "$moddir/FhemUtils"; + my @notes = ("thirdparty", $update); my $ret; my $result; @@ -156,12 +221,23 @@ update_CheckNotice($) my @unconfirmed; my @confirmed; - $result = AnalyzeCommandChain(undef, "notice get update 6"); - @published = split(",",$result) if($result); - $result = AnalyzeCommandChain(undef, "notice get update 7"); - @unconfirmed = split(",",$result) if($result); - $result = AnalyzeCommandChain(undef, "notice get update 8"); - @confirmed = split(",",$result) if($result); + if ($BRANCH ne "THIRDPARTY") { + $result = AnalyzeCommandChain(undef, "notice get update 6"); + @published = split(",",$result) if($result); + $result = AnalyzeCommandChain(undef, "notice get update 7"); + @unconfirmed = split(",",$result) if($result); + $result = AnalyzeCommandChain(undef, "notice get update 8"); + @confirmed = split(",",$result) if($result); + } else { + foreach my $note (@notes) { + $result = AnalyzeCommandChain(undef, "notice get $note 6"); + push(@published, split(",",$result)) if($result); + $result = AnalyzeCommandChain(undef, "notice get $note 7"); + push(@unconfirmed, split(",",$result)) if($result); + $result = AnalyzeCommandChain(undef, "notice get $note 8"); + push(@confirmed, split(",",$result)) if($result); + } + } # remove confirmed from published my %c; @@ -195,11 +271,11 @@ update_CheckNotice($) ( defined($cmdret) && grep (m/^$notice$/,@unconfirmed) && lc($cmdret) eq "after") || (!defined($cmdret) && grep (m/^$notice$/,@unconfirmed) && $position eq "before") || (!defined($cmdret) && !grep (m/^$notice$/,@unconfirmed) && $position eq "after") ) { - $ret .= "==> Message-ID: $notice\n"; + $ret .= "\n==> Message-ID: $notice\n"; my $noticeDE = AnalyzeCommandChain(undef, "notice view $notice noheader de"); my $noticeEN = AnalyzeCommandChain(undef, "notice view $notice noheader en"); if($noticeDE && $noticeEN) { - $ret .= "(English Translation: Please see below.)\n\n"; + # $ret .= "(English Translation: Please see below.)\n\n"; $ret .= $noticeDE; $ret .= "~~~~~~~~~~\n"; $ret .= $noticeEN; @@ -251,31 +327,52 @@ update_DoUpdate(@) my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; my $server = $UPDATE{server}; + my $uri; + my $url; + my $controlsTxt; + my @packages; my $fail; my $ret = ""; - # Get fhem.pl version - my $checkFhemRelease = update_CheckFhemRelease($force,$srcdir); - return $checkFhemRelease if ($checkFhemRelease); + if ($BRANCH ne "THIRDPARTY") { + # Get fhem.pl version + my $checkFhemRelease = update_CheckFhemRelease($force,$srcdir,$BRANCH); + return $checkFhemRelease if ($checkFhemRelease); + # set packages + @packages = split(" ",uc($UPDATE{packages})); + } else { + # set packages + @packages = ($update); + } # get list of files my $rControl_ref = {}; my $lControl_ref = {}; - foreach my $pack (split(" ",uc($UPDATE{packages}))) { - Log 3, "update get $server/$srcdir/$UPDATE{$pack}{control}"; - my $controlFile = GetFileFromURL("$server/$srcdir/$UPDATE{$pack}{control}"); - return "Can't get '$UPDATE{$pack}{control}' from $server" if (!$controlFile); + foreach my $pack (@packages) { + if ($BRANCH ne "THIRDPARTY") { + $controlsTxt = $UPDATE{$pack}{control}; + $uri = "$server/$srcdir/$controlsTxt"; + $url = "$server/$srcdir"; + } else { + $controlsTxt = "controls_$pack.txt"; + $uri = "$srcdir/$controlsTxt"; + $server = $srcdir; + $url = $server; + } + Log 3, "update get $uri"; + my $controlFile = GetFileFromURL($uri); + return "Can't get '$controlsTxt' from $server" if (!$controlFile); # parse remote controlfile ($fail,$rControl_ref) = update_ParseControlFile($pack,$controlFile,$rControl_ref,0); return "$fail\nUpdate canceled..." if ($fail); # parse local controlfile - ($fail,$lControl_ref) = update_ParseControlFile($pack,"$moddir/$UPDATE{$pack}{control}",$lControl_ref,1); + ($fail,$lControl_ref) = update_ParseControlFile($pack,"$moddir/$controlsTxt",$lControl_ref,1); return "$fail\nUpdate canceled..." if ($fail); } # Check for new / modified files - my ($checkUpdates,$updateFiles_ref) = update_CheckUpdates($update,$force,$lControl_ref,$rControl_ref); + my ($checkUpdates,$updateFiles_ref) = update_CheckUpdates($BRANCH,$update,$force,$lControl_ref,$rControl_ref); if (!keys %$updateFiles_ref) { return $checkUpdates; } else { @@ -309,19 +406,19 @@ update_DoUpdate(@) # get new / modified files my $getUpdates; - ($fail,$getUpdates) = update_GetRemoteFiles($srcdir,$updateFiles_ref,$cl); + ($fail,$getUpdates) = update_GetRemoteFiles($BRANCH,$url,$updateFiles_ref,$cl); $ret .= $getUpdates if($getUpdates); undef($updateFiles_ref); - foreach my $pack (split(" ",uc($UPDATE{packages}))) { + foreach my $pack (@packages) { # write local controlfile - my $localControlFile = update_WriteLocalControlFile($pack,$lControl_ref,$rControl_ref); + my $localControlFile = update_WriteLocalControlFile($BRANCH,$pack,$lControl_ref,$rControl_ref); $ret .= $localControlFile if ($localControlFile); } return $ret if($fail); - if (uc($update) eq "FULL" || uc($update) eq "FHEM") { - my $doHousekeeping = update_DoHousekeeping($update); + if (uc($update) eq "FHEM" || $BRANCH eq "THIRDPARTY") { + my $doHousekeeping = update_DoHousekeeping($BRANCH,$update); $ret .= $doHousekeeping if ($doHousekeeping); } @@ -331,19 +428,28 @@ update_DoUpdate(@) ######################################## sub -update_DoHousekeeping($) +update_DoHousekeeping($$) { - my ($update) = @_; + my ($BRANCH,$update) = @_; my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; my $cleanup; - my $pack = uc($update); + my $pack; my $ret; # parse local controlfile + my $controlsTxt; + if ($BRANCH ne "THIRDPARTY") { + $pack = uc($update); + $controlsTxt = $UPDATE{$pack}{control}; + } else { + $pack = $update; + $controlsTxt = "controls_$pack.txt"; + } + my $fail; my $lControl_ref; - ($fail,$lControl_ref) = update_ParseControlFile($pack,"$moddir/$UPDATE{$pack}{control}",$lControl_ref,1); + ($fail,$lControl_ref) = update_ParseControlFile($pack,"$moddir/$controlsTxt",$lControl_ref,1); return "$fail\nHousekeeping canceled..." if ($fail); @@ -431,9 +537,9 @@ update_DoHousekeeping($) ######################################## sub -update_CheckUpdates($$$$) +update_CheckUpdates($$$$$) { - my ($update,$force,$lControl_ref,$rControl_ref) = @_; + my ($BRANCH,$update,$force,$lControl_ref,$rControl_ref) = @_; return "Wildcards are not ( yet ;-) ) allowed." if ($update =~ /(\*|\?)/); my @exclude; @@ -447,11 +553,15 @@ update_CheckUpdates($$$$) my %updateFiles = (); # select package - $pack = "FHEM"; - $pack = uc($update) if ($force); + if($BRANCH ne "THIRDPARTY") { + $pack = "FHEM"; + $pack = uc($update) if ($force); + } else { + $pack = $update; + } # build searchstring - if (uc($update) ne "FULL" && uc($update) ne "FHEM") { + if (uc($update) ne "FHEM" && $BRANCH ne "THIRDPARTY") { $singleFile = 1; if ($update =~ m/^(\S+)\.(.*)$/) { $search = lc($1); @@ -509,7 +619,7 @@ update_CheckUpdates($$$$) last; } - next if (!$force && + next if (-e $f && !$force && $lControl{$pack}{$f}{date} && $rControl{$pack}{$f}{date} eq $lControl{$pack}{$f}{date}); @@ -567,9 +677,9 @@ update_CheckUpdates($$$$) ######################################## sub -update_GetRemoteFiles($$$) +update_GetRemoteFiles($$$$) { - my ($srcdir,$updateFiles_ref,$cl) = @_; + my ($BRANCH,$url,$updateFiles_ref,$cl) = @_; my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; my $server = $UPDATE{server}; @@ -586,11 +696,13 @@ update_GetRemoteFiles($$$) $remoteFile = $f; $localFile = "$modpath/$f"; - # mark for a restart of fhem.pl - if ($f =~ m/fhem.pl$/) { - $newFhem = 1; - $localFile = $0 if (! -d "updatefhem.dir"); - $remoteFile = "$f.txt"; + if ($BRANCH ne "THIRDPARTY") { + # mark for a restart of fhem.pl + if ($f =~ m/fhem.pl$/) { + $newFhem = 1; + $localFile = $0 if (! -d "updatefhem.dir"); + $remoteFile = "$f.txt"; + } } # replace special char % in filename @@ -602,8 +714,8 @@ update_GetRemoteFiles($$$) $fpath =~ s/$fname//g; # get remote File - Log 3, "update get $server/$srcdir/$remoteFile"; - my $fileContent = GetFileFromURL("$server/$srcdir/$remoteFile"); + Log 3, "update get $url/$remoteFile"; + my $fileContent = GetFileFromURL("$url/$remoteFile"); my $fileLength = length($fileContent); my $ctrlLength = $updateFiles_ref->{$f}->{size}; @@ -679,7 +791,7 @@ update_GetRemoteFiles($$$) #} } - if ($newFhem) { + if ($newFhem && $BRANCH ne "THIRDPARTY") { my $str = "A new version of fhem.pl was installed, 'shutdown restart' is required!"; Log 1, "update $str"; $ret .= "\n$str\n"; @@ -697,9 +809,9 @@ update_GetRemoteFiles($$$) ######################################## sub -update_ListChanges($) +update_ListChanges($$$) { - my ($srcdir) = @_; + my ($srcdir,$BRANCH,$update) = @_; my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; my $excluded = (!defined($attr{global}{exclude_from_update}) ? "" : $attr{global}{exclude_from_update}); @@ -707,14 +819,26 @@ update_ListChanges($) my $pack; my $server = $UPDATE{server}; my $ret = "List of new / modified files since last update:\n"; + my $uri; + my $localControlFile; + my $changedFile; - # select package - $pack = "FHEM"; + if($BRANCH ne "THIRDPARTY") { + $pack = "FHEM"; + $uri = "$server/$srcdir/$UPDATE{$pack}{control}"; + $localControlFile = "$moddir/$UPDATE{$pack}{control}"; + $changedFile = "$server/$srcdir/CHANGED"; + } else { + $pack = $update; + $uri = "$srcdir/controls_$update.txt"; + $localControlFile = "$moddir/controls_$update.txt"; + $changedFile = "$srcdir/CHANGED"; + } # get list of files - Log 3, "update get $server/$srcdir/$UPDATE{$pack}{control}"; - my $controlFile = GetFileFromURL("$server/$srcdir/$UPDATE{$pack}{control}"); - return "Can't get $UPDATE{$pack}{control} from $server" if (!$controlFile); + Log 3, "update get $uri"; + my $controlFile = GetFileFromURL($uri); + return "Can't get controlfile from $uri" if (!$controlFile); # parse remote controlfile my $rControl_ref = {};; @@ -723,7 +847,7 @@ update_ListChanges($) # parse local controlfile my $lControl_ref = {}; - ($fail,$lControl_ref) = update_ParseControlFile($pack,"$moddir/$UPDATE{$pack}{control}",$lControl_ref,1); + ($fail,$lControl_ref) = update_ParseControlFile($pack,$localControlFile,$lControl_ref,1); return "$fail" if ($fail); # Check for new / modified files @@ -751,7 +875,7 @@ update_ListChanges($) } else { # get list of changes $ret .= "\nList of last changes:\n"; - my $changed = GetFileFromURL("$server/$srcdir/CHANGED"); + my $changed = GetFileFromURL($changedFile); if (!$changed || $changed =~ m/Error 404/g) { $ret .= "Can't get list of changes from $server"; } else { @@ -768,9 +892,9 @@ update_ListChanges($) ######################################## sub -update_CheckFhemRelease($$) +update_CheckFhemRelease($$$) { - my ($force,$srcdir) = @_; + my ($force,$srcdir,$BRANCH) = @_; my $server = $UPDATE{server}; my $versRemote; my $ret = undef; @@ -820,13 +944,19 @@ update_CheckFhemRelease($$) ######################################## sub -update_WriteLocalControlFile($$$) +update_WriteLocalControlFile($$$$) { - my ($pack,$lControl_ref,$rControl_ref) = @_; + my ($BRANCH,$pack,$lControl_ref,$rControl_ref) = @_; my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); my $moddir = "$modpath/FHEM"; - return "Can't write $moddir/".$UPDATE{$pack}{control}.": $!" if (!open(FH, ">$moddir/".$UPDATE{$pack}{control})); - Log 5, "update write $moddir/".$UPDATE{$pack}{control}; + my $controlsTxt; + if ($BRANCH ne "THIRDPARTY") { + $controlsTxt = $UPDATE{$pack}{control}; + } else { + $controlsTxt = "controls_$pack.txt"; + } + return "Can't write $moddir/$controlsTxt: $!" if (!open(FH, ">$moddir/$controlsTxt")); + Log 5, "update write $moddir/$controlsTxt"; my %rControl = %$rControl_ref; my %lControl = %$lControl_ref; foreach my $f (sort keys %{$rControl{$pack}}) { @@ -845,21 +975,21 @@ update_WriteLocalControlFile($$$) $file = defined($lControl{$pack}{$f}{file}) ? $lControl{$pack}{$f}{file} : $rControl{$pack}{$f}{file}; } - Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $date $size $file"; + Log 5, "update $controlsTxt: $ctrl $date $size $file"; print FH "$ctrl $date $size $file\n"; } if ($ctrl eq "DIR") { - Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $file"; + Log 5, "update $controlsTxt: $ctrl $file"; print FH "$ctrl $file\n"; } if ($ctrl eq "MOV") { - Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $file $move"; + Log 5, "update $controlsTxt: $ctrl $file $move"; print FH "$ctrl $file $move\n"; } if ($ctrl eq "DEL") { - Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $file"; + Log 5, "update $controlsTxt: $ctrl $file"; print FH "$ctrl $file\n"; } @@ -1004,23 +1134,29 @@ update_MakeDirectory($)

update

    - update [development|stable] [<file>|check|fhem|full] [force]
    + FHEM update / check for updates: +
    + update [development|stable] [<file|package>] [force]
    + update [development|stable] check
    + update housekeeping

    + Third party package update / check for a package update: +
    + update thirdparty <url> <package> [force]
    + update thirdparty <url> <package> check

    The installed fhem distribution and its installed extensions (just like the webGUI PGM2) are updated via this command from the online repository. The locally installed files will be checked against the online repository and - will be updated in case the files online are in a newer version. Modules - which are used while the update is in progress will be restarted in the new - version after the update has finished. + will be updated in case the files online are in a newer version.

    - The new update function will process more advanced distribution information + The update function will process more advanced distribution information as well as control commands for updating, removing or renaming existing files. - New file structures can also be set up by the new control command files. - The new update process will exclusively work with the file path which is + New file structures can also be set up via control command files. + The update process will exclusively work with the file path which is given by the global attribute "modpath" except for the fhem.pl file. The user - decides whether to use a stable, a developer- or a experimental-rated version - of fhem (experimental is not yet implemented). + decides whether to use a stable, or a developer-rated version of fhem. + stable is not yet implemented, so an update use always the developer-rated version.

    Furthermore, the use of packages is supported just like in a manual installation @@ -1029,6 +1165,46 @@ update_MakeDirectory($) used will be updated.

    + The update function supports the installation of third-party packages like + modules or GUIs that are not part of the FHEM distribution. +
    +
    + Notice for Developers of third-party packages: +
    + Further information can be obtained from the file 'docs/LIESMICH.update-thirdparty'. +
    +
    + Examples: +
    Check for new updates:
    +    fhem> update check
    +    
    + +
    FHEM update:
    +    fhem> update
    +    
    + +
    Force FHEM update (all files are updated!):
    +    fhem> update force
    +    
    + +
    Update a single file:
    +    fhem> update 98_foobar.pm
    +    
    + +
    Search for a filename:
    +    fhem> update backup
    +    'backup' not found. Did you mean:
    +    ==> 98_backup.pm
    +    nothing to do...
    +    
    + +
    Update / install a third-party package:
    +    fhem> update thirdparty http://domain.tld/path packagename
    +    
    + +
    Check a third-party package for new updates:
    +    fhem> update thirdparty http://domain.tld/path packagename check
    +    
    Attributes @@ -1042,4 +1218,96 @@ update_MakeDirectory($)
=end html +=begin html_DE + + +

update

+
    + FHEM aktualisieren / auf Aktualisierungen prüfen: +
    + update [development|stable] [<Date|Paket>] [force]
    + update [development|stable] check
    + update housekeeping

    + Aktualisierung eines Fremdpaketes / Fremdpaket auf Aktualisierungen prüfen: +
    + update thirdparty <url> <Paketname> [force]
    + update thirdparty <url> <Paketname> check
    +
    + Die installierte FHEM Distribution und deren Erweiterungen (z.B. das Web-Interface + PGM2 (FHEMWEB)) werden mit diesem Befehl über ein Online Repository aktualisiert. + Enthält das Repository neuere Dateien oder Dateiversionen als die lokale + Installation, werden die aktualisierten Dateien aus dem Repository installiert. +
    +
    + Die Update-Funktion unterstützt erweiterte Distributions Informationen sowie + die Steuerung über spezielle Befehle zum aktualisieren, verschieben oder + umbenennen von bestehenden Dateien. Neue Verzeichnisstrukturen können ebenfalls + über die Aktualisierung erzeugt werden. Die Aktualisierung erfolgt exklusiv + im Verzeichnispfad der über das globale Attribut "modpath" gesetzt wurde + (Ausnahme: fhem.pl). Der Anwender kann die Aktualisierung wahlweise + aus dem stabilen (stable) oder Entwicklungs-Zweig (development) vornehmen lassen. + Ein Aktualisierung erfolgt zur Zeit ausschliesslich nur über den + Entwicklungs-Zweig (development). +
    +
    + Weiterhin unterstützt der update Befehl die manuelle Installation von Paketen + die Bestandteil der FHEM Distribution sind. Aktuell werden noch keine erweiterten FHEM + Pakete bereitgestellt. +
    +
    + Der update Befehl unterstützt auch die Installation von Paketen die kein Bestandteil + der FHEM Distribution sind. Diese Pakete können z.B. von Entwicklern angebotene + Module oder Benutzerinterfaces beinhalten. +
    +
    + Hinweis für Anbieter von zusätzlichen Paketen: +
    + Weiterführende Informationen zur Bereitstellung von Paketen sind der Datei + 'docs/LIESMICH.update-thirdparty' zu entnehmen. +
    +
    + Beispiele: +
    Auf neue Aktualisierungen prüfen:
    +    fhem> update check
    +    
    + +
    FHEM aktualisieren:
    +    fhem> update
    +    
    + +
    FHEM Aktualisierung erzwingen (alle Dateien werden aktualisiert!):
    +    fhem> update force
    +    
    + +
    Eine einzelne Datei aktualisieren:
    +    fhem> update 98_foobar.pm
    +    
    + +
    Nach einem Dateinamen suchen:
    +    fhem> update backup
    +    'backup' not found. Did you mean:
    +    ==> 98_backup.pm
    +    nothing to do...
    +    
    + +
    Aktualisierung oder Installation eines Fremdpaketes:
    +    fhem> update thirdparty http://domain.tld/path paketname
    +    
    + +
    Fremdpaket auf neue Aktualisierungen prüfen:
    +    fhem> update thirdparty http://domain.tld/path paketname check
    +    
    + + + Attribute + +
+ +=end html_DE =cut diff --git a/fhem/docs/LIESMICH.update-thirdparty b/fhem/docs/LIESMICH.update-thirdparty new file mode 100644 index 000000000..675393009 --- /dev/null +++ b/fhem/docs/LIESMICH.update-thirdparty @@ -0,0 +1,145 @@ +# $id:$ +LIESMICH.update-thirdparty - Bereitstellung von Fremdpaketen + +Beschreibung + + Der in FHEM integrierte Updateprozess unterstützt die Installation von Paketen + die kein Bestandteil der Distribution sind. Dies soll die Verteilung von + Erweiterungen ermöglichen, die nicht in den regulären Aktualisierungsvorgang + aufgenommen werden können oder sollen. Entwicklern wird damit die Möglichkeit + angeboten ihre Pakete über ein eigenes Repository zu verteilen. + +Updateprozess + + Eine Aktualisierung wird in der FHEM Befehlszeile (alternativ über das + Eingabefeld von FHEMWEB) über den Befehl 'update' angestossen. Der Anwender + kann dabei das Verhalten über Parameter beeinflussen. + + Der 'update' Befehl unterstützt dabei die optionale Angabe des BRANCH stable + oder development. Je nach Angabe wird die Aktualisierung aus dem entsprechendem + Updatepfad auf fhem.de (stable / development) vorgenommen. Zur Zeit unterstützt + FHEM nur Aktualisierungen aus dem Entwicklungszweig. + + Darüber hinaus unterstützt der 'update' Befehl die Bereitstellung von FHEM + eigenen Paketen. Diese Funktionalität wurde im Rahmen der Entwicklung + bereitgestellt um z.B. eine getrennte Installation der FHEM-core Dateien und + FHEMWEB zu ermöglichen. Aktuell wird nur das Paket "fhem" angeboten das alle + Dateien der jeweiligen Release beinhaltet. + + Im jeweiligem Repository (stable / development) wird eine Steuerungsdatei + vorgehalten. Diese Steuerungsdatei hat die Bezeichnung 'controls_.txt', + wobei als Platzhalter für das entsprechende Paket steht. Im Beispiel + von FHEM lautet die Steuerungsdatei 'controls_fhem.txt'. + + Damit sich der Anwender vor einer Aktualisierung über Neuerungen informieren + kann, wird neben der zwingend notwendigen Steuerungsdatei ein Changelog über + die Datei CHANGED bereitgestellt. + + Unmittelbar nach dem Aufruf des 'update' Befehls wird die Steuerungsdatei auf + das lokale System übertragen und auf Inkonsistenzen im Aufbau überprüft. Zur + Zeit werden folgende Steuerbefehle unterstützt: + + UPD - Zu aktualisierende Datei + DIR - Zu erstellendes Verzeichnis + MOV - Zu verschiebende Datei(en) + DEL - Zu löschende Datei(en) / Verzeichnisse + + Durch die Integration des FHEM Befehls 'notice' besteht die Möglichkeit vor + oder nach der Verabeitung der Steuerdatei Hinweise anzeigen zu lassen und + bei Bedarf eine Bestätigung des Nutzers einzuholen. 'notice' unterstützt dabei + ebenfalls die Abfrage von Variablen. Weiterführende Informationen sind der + Anleitung von 'notice' zu entnehmen. + + Nach dem alle zu aktualisierenden Dateien installiert wurden, wird abschliessend + ein 'Housekeeping' vorgenommen. In diesem Schritt werden die Steuerbefehle + DIR, MOV, DEL (in genau dieser Reihenfolge) verarbeitet. + +Struktur des Update-Repository + + Das Repository beinhaltet die komplett abzubildene Struktur des zu installierenden + Paketes. Es wird empfohlen auf dem Webserver ein eigenes Verzeichnis für jedes + Paket bereit zu stellen. + + Beispielstruktur für das Paket 'mypackage': + + CHANGED + controls_mypackage.txt + FHEM/FhemUtils/mypackage-20130222-001 + FHEM/98_myPackageModule.pm + www/myPackage/index.html + + Um das Paket 'mypackage' über den 'update' Befehl zu installieren, benötigt der + Anwender die URL inkl. der Pfadangabe zur Steuerungsdatei sowie den Paketnamen. + Die URL beinhaltet nicht die Angabe der Steuerungsdatei, der Paketname sollte + in Kleinbuchstaben weitergegeben werden. + Beispiel: + 'update http://my_domain.tld/my_package_path mypackage' + +Struktur der Steuerungsdatei + + Die Steuerungsdatei beinhaltet die zu aktualisierenden Dateien und ggf. zu + erstellende Verzeichnisse. Dabei ist der Aufbau exakt dem Beispiel zu entnehmen. + Die Steuerungsdatei muss den Namen des Paketes beinhalten. Der Installationspfad + einzelner Dateien kann sich nur unterhalb des Pfades gemäß dem globalen Attribut + 'modpath' befinden (zum Schutz der Installationsumgebung). + + Inhalt der Steuerungsdatei 'controls_mypackage.txt' für das Paket 'mypackage': + + DIR www/myPackage + UPD 2013-02-22_20:15:00 46 www/myPackage/index.html + UPD 2013-02-22_20:15:00 257 FHEM/98_myPackage.pm + UPD 2013-02-22_20:15:00 246 FHEM/FhemUtils/mypackage-20130222-001 + + In diesem Beispiel wird das Verzeichnis 'www/myPackage' unterhalb von 'modpath' + erzeugt. Es wird geprüft ob die Dateien + + www/myPackage/index.html + FHEM/98_myPackage.pm + FHEM/FhemUtils/mypackage-20130222-001 + + nicht vorhanden oder älter als der angegebene Zeitstempel sind. Trift einer der + Fälle zu, wird die entsprechende Datei aktualisiert (UPD). + + Dabei sind folgende Vorgaben einzuhalten: + + UPD + benötigt die Angabe eines Zeitstempels, der Dateigröße sowie dem Dateinamen + inkl. dem Pfad. Dabei ist die Schreibweise des Zeitstempels beizubehalten. + Beispiel: + UPD 2013-02-22_20:15:00 257 FHEM/98_myPackage.pm + + DIR + benötigt den Pfad unterhalb von 'modpath' des zu erzeugenden Verzeichnisses. + Beispiel: + DIR www/myPackage + + DEL + benötigt die Angabe des Dateinamens (alternativ Glob) inkl. Pfad der zu + löschenden Datei(en). + Beispiel: + DEL www/myPackage/*.bak + + MOV + benötigt die Angabe der Quelle und des Zieles. Glob wird unterstützt. + Beispiel: + MOV www/myPackage/*.jpg www/myPackage/images + +Hinweis für Anbieter von Fremdpaketen + + Anbieter von Paketen die nicht zur FHEM Distribution gehören achten bitte + eigenverantwortlich darauf, das die zur FHEM Distribution gehörenden Dateien + nicht gelöscht, verändert, o.ä. werden ohne den Anwender darauf aufmerksam + zu machen. Ein solcher Eingriff sollte nur mit Bedacht und der Sicherstellung + der Funktionalität von FHEM vorgenommen werden. Dabei sind auch evtuelle + Seiteneffekte zu berücksichtigen. Ein (ungetesteter) Eingriff in die FHEM + Umgebung kann zu einem erhöhtem Supportaufwand führen. Die Fehlersuche wird + ggf. für anderen Entwickler erschwert. Ebenfalls sollte der Einsatz von + Hinweisen über den Befehl 'notice' wohl dosiert erfolgen. + + FHEM steht unter der GNU General Public License v2 oder höher. Anbieter haben + bei der Verteilung von Software ebenfalls eigenverantwortlich auf die + Einhaltung der jeweiligen Lizenzen und gültige Rechtsgrundlagen zu achten. + +Autor + Martin Fischer (m_fischer at gmx dot de), Februar 2013 +