added support for third-party packages to update.pm
git-svn-id: https://svn.fhem.de/fhem/trunk@2788 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
- feature: added new Javascript Frontend based on ExtJS (by Johannes)
|
- feature: added new Javascript Frontend based on ExtJS (by Johannes)
|
||||||
- feature: new Modules 30_HUEDevice and 31_HUEBridge for phillips hue and
|
- feature: new Modules 30_HUEDevice and 31_HUEBridge for phillips hue and
|
||||||
smartlink devices (by justme1968)
|
smartlink devices (by justme1968)
|
||||||
- change: SYSSTAT: allow remote monitoring by ssh
|
- change: SYSSTAT: allow remote monitoring by ssh
|
||||||
- change: SYSSTAT: allow less frequent updates for diskusage
|
- change: SYSSTAT: allow less frequent updates for diskusage
|
||||||
- feature: new Module 32_SYSSTAT to monitor system load and disk usage
|
- feature: new Module 32_SYSSTAT to monitor system load and disk usage
|
||||||
on linux FHEM hosts (by justme1968)
|
on linux FHEM hosts (by justme1968)
|
||||||
- feature: new Module 73_PRESENCE to make automatic presence detection of
|
- feature: new Module 73_PRESENCE to make automatic presence detection of
|
||||||
@@ -89,6 +89,7 @@
|
|||||||
smallscreen/touchpad moved to stylesheetPrefix, menuEntries
|
smallscreen/touchpad moved to stylesheetPrefix, menuEntries
|
||||||
added, Extend devStateIcon, js setting of attr values in detail
|
added, Extend devStateIcon, js setting of attr values in detail
|
||||||
screen, live slider update in detail and room view
|
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)
|
- 2012-10-28 (5.3)
|
||||||
- feature: added functions trim, ltrim, rtrim, UntoggleDirect,
|
- feature: added functions trim, ltrim, rtrim, UntoggleDirect,
|
||||||
|
|||||||
@@ -1,10 +1,26 @@
|
|||||||
################################################################
|
################################################################
|
||||||
# $Id$
|
# $Id$
|
||||||
# vim: ts=2:et
|
# vim: ts=2:et
|
||||||
|
################################################################
|
||||||
#
|
#
|
||||||
# (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de)
|
# (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de)
|
||||||
# All rights reserved
|
# 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;
|
package main;
|
||||||
use strict;
|
use strict;
|
||||||
@@ -13,18 +29,17 @@ use HttpUtils;
|
|||||||
use File::Copy qw(cp mv);
|
use File::Copy qw(cp mv);
|
||||||
|
|
||||||
sub CommandUpdate($$);
|
sub CommandUpdate($$);
|
||||||
sub update_CheckFhemRelease($$);
|
sub update_CheckFhemRelease($$$);
|
||||||
sub update_CheckUpdates($$$$);
|
sub update_CheckNotice($$$);
|
||||||
|
sub update_CheckUpdates($$$$$);
|
||||||
sub update_CleanUpLocalFiles($$$);
|
sub update_CleanUpLocalFiles($$$);
|
||||||
sub update_DoUpdate(@);
|
sub update_DoUpdate(@);
|
||||||
sub update_DoHousekeeping($);
|
sub update_DoHousekeeping($$);
|
||||||
sub update_GetRemoteFiles($$$);
|
sub update_GetRemoteFiles($$$$);
|
||||||
sub update_ListChanges($);
|
sub update_ListChanges($$$);
|
||||||
sub update_MakeDirectory($);
|
sub update_MakeDirectory($);
|
||||||
sub update_ParseControlFile($$$$);
|
sub update_ParseControlFile($$$$);
|
||||||
sub update_WriteLocalControlFile($$$);
|
sub update_WriteLocalControlFile($$$$);
|
||||||
|
|
||||||
my $BRANCH;
|
|
||||||
|
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
@@ -62,7 +77,7 @@ CommandUpdate($$)
|
|||||||
my @args = split(/ +/,$param);
|
my @args = split(/ +/,$param);
|
||||||
|
|
||||||
# set default trunk
|
# 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") {
|
if ($BRANCH ne "STABLE" && $BRANCH ne "DEVELOPMENT") {
|
||||||
$ret = "global attribute 'updatebranch': unknown keyword: '$BRANCH'. Keyword should be 'STABLE' or 'DEVELOPMENT'";
|
$ret = "global attribute 'updatebranch': unknown keyword: '$BRANCH'. Keyword should be 'STABLE' or 'DEVELOPMENT'";
|
||||||
Log 1, "update $ret";
|
Log 1, "update $ret";
|
||||||
@@ -71,36 +86,71 @@ CommandUpdate($$)
|
|||||||
|
|
||||||
if (!defined($args[0])) {
|
if (!defined($args[0])) {
|
||||||
push(@args,$BRANCH);
|
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);
|
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]);
|
$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
|
# check arguments
|
||||||
if (defined($args[1]) && $args[1] eq "?" ||
|
if (defined($args[1]) && $args[1] eq "?") {
|
||||||
(int(@args) > 3 && uc($args[1]) eq "HOUSEKEEPING") ||
|
# return complete usage
|
||||||
(int(@args) > 2 && uc($args[2]) ne "FORCE" &&
|
$ret = "Usage:\n";
|
||||||
(uc($args[1]) eq "CHECK" ||
|
$ret .= "=> FHEM update / check for updates:\n";
|
||||||
uc($args[1]) eq "FHEM" ||
|
$ret .= "\tupdate [development|stable] [<file|package>] [force]\n";
|
||||||
uc($args[1]) eq "FULL")) ||
|
$ret .= "\tupdate [development|stable] check\n";
|
||||||
(int(@args) > 2 &&
|
$ret .= "\tupdate housekeeping\n";
|
||||||
(uc($args[1]) ne "CHECK" &&
|
$ret .= "=> Third party package update / check for a package update:\n";
|
||||||
uc($args[1]) ne "FHEM" &&
|
$ret .= "\tupdate thirdparty <url> <package> [force]\n";
|
||||||
uc($args[1]) ne "FULL" &&
|
$ret .= "\tupdate thirdparty <url> <package> check";
|
||||||
uc($args[1]) ne "HOUSEKEEPING"))) {
|
return $ret;
|
||||||
return "Usage: update [development|stable] [<file>|check|fhem|full] [force]";
|
|
||||||
}
|
} elsif (int(@args) <= 2 && $BRANCH eq "THIRDPARTY") {
|
||||||
|
# missing arguments for third party package
|
||||||
|
$ret = "Usage:\n";
|
||||||
|
$ret .= "\tupdate thirdparty <url> <package|file> [force]\n";
|
||||||
|
$ret .= "\tupdate thirdparty <url> <package> 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 <url> <package> 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 <url> <package> [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] <package> [force]";
|
||||||
|
}
|
||||||
|
|
||||||
# check arguments for housekeeping
|
|
||||||
if (defined($args[1]) && uc($args[1]) eq "HOUSEKEEPING" && (int(@args) > 2 )) {
|
|
||||||
return "Usage: update housekeeping";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# set default update
|
# set default update
|
||||||
@@ -109,30 +159,44 @@ CommandUpdate($$)
|
|||||||
(uc($args[1]) eq "FORCE") ||
|
(uc($args[1]) eq "FORCE") ||
|
||||||
uc($args[1]) eq "HOUSEKEEPING")) {
|
uc($args[1]) eq "HOUSEKEEPING")) {
|
||||||
$update = "FHEM";
|
$update = "FHEM";
|
||||||
|
} elsif (exists $UPDATE{uc($args[1])}) {
|
||||||
|
$update = uc($args[1]);
|
||||||
} else {
|
} else {
|
||||||
$update = $args[1];
|
$update = $args[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
# force update
|
# build sourcedir for update
|
||||||
$force = 1 if (defined($args[1]) && uc($args[1]) eq "FORCE" ||
|
if ($BRANCH ne "THIRDPARTY") {
|
||||||
defined($args[2]) && uc($args[2]) eq "FORCE");
|
# 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") {
|
# force update
|
||||||
$ret = update_ListChanges($srcdir);
|
$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") {
|
} elsif (defined($args[1]) && uc($args[1]) eq "HOUSEKEEPING") {
|
||||||
$ret = update_DoHousekeeping($update);
|
$ret = update_DoHousekeeping($BRANCH,$update);
|
||||||
$ret = "nothing to do..." if (!$ret);
|
$ret = "nothing to do..." if (!$ret);
|
||||||
} else {
|
} else {
|
||||||
my $unconfirmed;
|
my $unconfirmed;
|
||||||
my $notice;
|
my $notice;
|
||||||
($notice,$unconfirmed) = update_CheckNotice("before");
|
($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"before");
|
||||||
$ret .= $notice if(defined($notice));
|
$ret .= $notice if(defined($notice));
|
||||||
return $ret if($unconfirmed);
|
return $ret if($unconfirmed);
|
||||||
$ret .= update_DoUpdate($srcdir,$BRANCH,$update,$force,$cl);
|
$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));
|
$ret .= $notice if(defined($notice));
|
||||||
my $sendStatistics = AttrVal("global","sendStatistics",undef);
|
my $sendStatistics = AttrVal("global","sendStatistics",undef);
|
||||||
if(lc($sendStatistics) eq "onupdate") {
|
if(defined($sendStatistics) && lc($sendStatistics) eq "onupdate") {
|
||||||
$ret .= "\n\n";
|
$ret .= "\n\n";
|
||||||
$ret .= AnalyzeCommandChain(undef, "fheminfo send");
|
$ret .= AnalyzeCommandChain(undef, "fheminfo send");
|
||||||
}
|
}
|
||||||
@@ -143,12 +207,13 @@ CommandUpdate($$)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
sub
|
||||||
update_CheckNotice($)
|
update_CheckNotice($$$)
|
||||||
{
|
{
|
||||||
my ($position) = shift;
|
my ($BRANCH,$update,$position) = @_;
|
||||||
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
my $noticeDir = "$moddir/FhemUtils";
|
my $noticeDir = "$moddir/FhemUtils";
|
||||||
|
my @notes = ("thirdparty", $update);
|
||||||
my $ret;
|
my $ret;
|
||||||
my $result;
|
my $result;
|
||||||
|
|
||||||
@@ -156,12 +221,23 @@ update_CheckNotice($)
|
|||||||
my @unconfirmed;
|
my @unconfirmed;
|
||||||
my @confirmed;
|
my @confirmed;
|
||||||
|
|
||||||
$result = AnalyzeCommandChain(undef, "notice get update 6");
|
if ($BRANCH ne "THIRDPARTY") {
|
||||||
@published = split(",",$result) if($result);
|
$result = AnalyzeCommandChain(undef, "notice get update 6");
|
||||||
$result = AnalyzeCommandChain(undef, "notice get update 7");
|
@published = split(",",$result) if($result);
|
||||||
@unconfirmed = split(",",$result) if($result);
|
$result = AnalyzeCommandChain(undef, "notice get update 7");
|
||||||
$result = AnalyzeCommandChain(undef, "notice get update 8");
|
@unconfirmed = split(",",$result) if($result);
|
||||||
@confirmed = 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
|
# remove confirmed from published
|
||||||
my %c;
|
my %c;
|
||||||
@@ -195,11 +271,11 @@ update_CheckNotice($)
|
|||||||
( defined($cmdret) && grep (m/^$notice$/,@unconfirmed) && lc($cmdret) eq "after") ||
|
( 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 "before") ||
|
||||||
(!defined($cmdret) && !grep (m/^$notice$/,@unconfirmed) && $position eq "after") ) {
|
(!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 $noticeDE = AnalyzeCommandChain(undef, "notice view $notice noheader de");
|
||||||
my $noticeEN = AnalyzeCommandChain(undef, "notice view $notice noheader en");
|
my $noticeEN = AnalyzeCommandChain(undef, "notice view $notice noheader en");
|
||||||
if($noticeDE && $noticeEN) {
|
if($noticeDE && $noticeEN) {
|
||||||
$ret .= "(English Translation: Please see below.)\n\n";
|
# $ret .= "(English Translation: Please see below.)\n\n";
|
||||||
$ret .= $noticeDE;
|
$ret .= $noticeDE;
|
||||||
$ret .= "~~~~~~~~~~\n";
|
$ret .= "~~~~~~~~~~\n";
|
||||||
$ret .= $noticeEN;
|
$ret .= $noticeEN;
|
||||||
@@ -251,31 +327,52 @@ update_DoUpdate(@)
|
|||||||
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
my $server = $UPDATE{server};
|
my $server = $UPDATE{server};
|
||||||
|
my $uri;
|
||||||
|
my $url;
|
||||||
|
my $controlsTxt;
|
||||||
|
my @packages;
|
||||||
my $fail;
|
my $fail;
|
||||||
my $ret = "";
|
my $ret = "";
|
||||||
|
|
||||||
# Get fhem.pl version
|
if ($BRANCH ne "THIRDPARTY") {
|
||||||
my $checkFhemRelease = update_CheckFhemRelease($force,$srcdir);
|
# Get fhem.pl version
|
||||||
return $checkFhemRelease if ($checkFhemRelease);
|
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
|
# get list of files
|
||||||
my $rControl_ref = {};
|
my $rControl_ref = {};
|
||||||
my $lControl_ref = {};
|
my $lControl_ref = {};
|
||||||
foreach my $pack (split(" ",uc($UPDATE{packages}))) {
|
foreach my $pack (@packages) {
|
||||||
Log 3, "update get $server/$srcdir/$UPDATE{$pack}{control}";
|
if ($BRANCH ne "THIRDPARTY") {
|
||||||
my $controlFile = GetFileFromURL("$server/$srcdir/$UPDATE{$pack}{control}");
|
$controlsTxt = $UPDATE{$pack}{control};
|
||||||
return "Can't get '$UPDATE{$pack}{control}' from $server" if (!$controlFile);
|
$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
|
# parse remote controlfile
|
||||||
($fail,$rControl_ref) = update_ParseControlFile($pack,$controlFile,$rControl_ref,0);
|
($fail,$rControl_ref) = update_ParseControlFile($pack,$controlFile,$rControl_ref,0);
|
||||||
return "$fail\nUpdate canceled..." if ($fail);
|
return "$fail\nUpdate canceled..." if ($fail);
|
||||||
|
|
||||||
# parse local controlfile
|
# 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);
|
return "$fail\nUpdate canceled..." if ($fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for new / modified files
|
# 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) {
|
if (!keys %$updateFiles_ref) {
|
||||||
return $checkUpdates;
|
return $checkUpdates;
|
||||||
} else {
|
} else {
|
||||||
@@ -309,19 +406,19 @@ update_DoUpdate(@)
|
|||||||
|
|
||||||
# get new / modified files
|
# get new / modified files
|
||||||
my $getUpdates;
|
my $getUpdates;
|
||||||
($fail,$getUpdates) = update_GetRemoteFiles($srcdir,$updateFiles_ref,$cl);
|
($fail,$getUpdates) = update_GetRemoteFiles($BRANCH,$url,$updateFiles_ref,$cl);
|
||||||
$ret .= $getUpdates if($getUpdates);
|
$ret .= $getUpdates if($getUpdates);
|
||||||
undef($updateFiles_ref);
|
undef($updateFiles_ref);
|
||||||
|
|
||||||
foreach my $pack (split(" ",uc($UPDATE{packages}))) {
|
foreach my $pack (@packages) {
|
||||||
# write local controlfile
|
# 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);
|
$ret .= $localControlFile if ($localControlFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret if($fail);
|
return $ret if($fail);
|
||||||
if (uc($update) eq "FULL" || uc($update) eq "FHEM") {
|
if (uc($update) eq "FHEM" || $BRANCH eq "THIRDPARTY") {
|
||||||
my $doHousekeeping = update_DoHousekeeping($update);
|
my $doHousekeeping = update_DoHousekeeping($BRANCH,$update);
|
||||||
$ret .= $doHousekeeping if ($doHousekeeping);
|
$ret .= $doHousekeeping if ($doHousekeeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,19 +428,28 @@ update_DoUpdate(@)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
sub
|
||||||
update_DoHousekeeping($)
|
update_DoHousekeeping($$)
|
||||||
{
|
{
|
||||||
my ($update) = @_;
|
my ($BRANCH,$update) = @_;
|
||||||
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
my $cleanup;
|
my $cleanup;
|
||||||
my $pack = uc($update);
|
my $pack;
|
||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
# parse local controlfile
|
# 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 $fail;
|
||||||
my $lControl_ref;
|
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);
|
return "$fail\nHousekeeping canceled..." if ($fail);
|
||||||
|
|
||||||
|
|
||||||
@@ -431,9 +537,9 @@ update_DoHousekeeping($)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
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 =~ /(\*|\?)/);
|
return "Wildcards are not ( yet ;-) ) allowed." if ($update =~ /(\*|\?)/);
|
||||||
|
|
||||||
my @exclude;
|
my @exclude;
|
||||||
@@ -447,11 +553,15 @@ update_CheckUpdates($$$$)
|
|||||||
my %updateFiles = ();
|
my %updateFiles = ();
|
||||||
|
|
||||||
# select package
|
# select package
|
||||||
$pack = "FHEM";
|
if($BRANCH ne "THIRDPARTY") {
|
||||||
$pack = uc($update) if ($force);
|
$pack = "FHEM";
|
||||||
|
$pack = uc($update) if ($force);
|
||||||
|
} else {
|
||||||
|
$pack = $update;
|
||||||
|
}
|
||||||
|
|
||||||
# build searchstring
|
# build searchstring
|
||||||
if (uc($update) ne "FULL" && uc($update) ne "FHEM") {
|
if (uc($update) ne "FHEM" && $BRANCH ne "THIRDPARTY") {
|
||||||
$singleFile = 1;
|
$singleFile = 1;
|
||||||
if ($update =~ m/^(\S+)\.(.*)$/) {
|
if ($update =~ m/^(\S+)\.(.*)$/) {
|
||||||
$search = lc($1);
|
$search = lc($1);
|
||||||
@@ -509,7 +619,7 @@ update_CheckUpdates($$$$)
|
|||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
next if (!$force &&
|
next if (-e $f && !$force &&
|
||||||
$lControl{$pack}{$f}{date} &&
|
$lControl{$pack}{$f}{date} &&
|
||||||
$rControl{$pack}{$f}{date} eq $lControl{$pack}{$f}{date});
|
$rControl{$pack}{$f}{date} eq $lControl{$pack}{$f}{date});
|
||||||
|
|
||||||
@@ -567,9 +677,9 @@ update_CheckUpdates($$$$)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
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 $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
my $server = $UPDATE{server};
|
my $server = $UPDATE{server};
|
||||||
@@ -586,11 +696,13 @@ update_GetRemoteFiles($$$)
|
|||||||
$remoteFile = $f;
|
$remoteFile = $f;
|
||||||
$localFile = "$modpath/$f";
|
$localFile = "$modpath/$f";
|
||||||
|
|
||||||
# mark for a restart of fhem.pl
|
if ($BRANCH ne "THIRDPARTY") {
|
||||||
if ($f =~ m/fhem.pl$/) {
|
# mark for a restart of fhem.pl
|
||||||
$newFhem = 1;
|
if ($f =~ m/fhem.pl$/) {
|
||||||
$localFile = $0 if (! -d "updatefhem.dir");
|
$newFhem = 1;
|
||||||
$remoteFile = "$f.txt";
|
$localFile = $0 if (! -d "updatefhem.dir");
|
||||||
|
$remoteFile = "$f.txt";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# replace special char % in filename
|
# replace special char % in filename
|
||||||
@@ -602,8 +714,8 @@ update_GetRemoteFiles($$$)
|
|||||||
$fpath =~ s/$fname//g;
|
$fpath =~ s/$fname//g;
|
||||||
|
|
||||||
# get remote File
|
# get remote File
|
||||||
Log 3, "update get $server/$srcdir/$remoteFile";
|
Log 3, "update get $url/$remoteFile";
|
||||||
my $fileContent = GetFileFromURL("$server/$srcdir/$remoteFile");
|
my $fileContent = GetFileFromURL("$url/$remoteFile");
|
||||||
my $fileLength = length($fileContent);
|
my $fileLength = length($fileContent);
|
||||||
my $ctrlLength = $updateFiles_ref->{$f}->{size};
|
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!";
|
my $str = "A new version of fhem.pl was installed, 'shutdown restart' is required!";
|
||||||
Log 1, "update $str";
|
Log 1, "update $str";
|
||||||
$ret .= "\n$str\n";
|
$ret .= "\n$str\n";
|
||||||
@@ -697,9 +809,9 @@ update_GetRemoteFiles($$$)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
sub
|
||||||
update_ListChanges($)
|
update_ListChanges($$$)
|
||||||
{
|
{
|
||||||
my ($srcdir) = @_;
|
my ($srcdir,$BRANCH,$update) = @_;
|
||||||
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
my $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
my $excluded = (!defined($attr{global}{exclude_from_update}) ? "" : $attr{global}{exclude_from_update});
|
my $excluded = (!defined($attr{global}{exclude_from_update}) ? "" : $attr{global}{exclude_from_update});
|
||||||
@@ -707,14 +819,26 @@ update_ListChanges($)
|
|||||||
my $pack;
|
my $pack;
|
||||||
my $server = $UPDATE{server};
|
my $server = $UPDATE{server};
|
||||||
my $ret = "List of new / modified files since last update:\n";
|
my $ret = "List of new / modified files since last update:\n";
|
||||||
|
my $uri;
|
||||||
|
my $localControlFile;
|
||||||
|
my $changedFile;
|
||||||
|
|
||||||
# select package
|
if($BRANCH ne "THIRDPARTY") {
|
||||||
$pack = "FHEM";
|
$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
|
# get list of files
|
||||||
Log 3, "update get $server/$srcdir/$UPDATE{$pack}{control}";
|
Log 3, "update get $uri";
|
||||||
my $controlFile = GetFileFromURL("$server/$srcdir/$UPDATE{$pack}{control}");
|
my $controlFile = GetFileFromURL($uri);
|
||||||
return "Can't get $UPDATE{$pack}{control} from $server" if (!$controlFile);
|
return "Can't get controlfile from $uri" if (!$controlFile);
|
||||||
|
|
||||||
# parse remote controlfile
|
# parse remote controlfile
|
||||||
my $rControl_ref = {};;
|
my $rControl_ref = {};;
|
||||||
@@ -723,7 +847,7 @@ update_ListChanges($)
|
|||||||
|
|
||||||
# parse local controlfile
|
# parse local controlfile
|
||||||
my $lControl_ref = {};
|
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);
|
return "$fail" if ($fail);
|
||||||
|
|
||||||
# Check for new / modified files
|
# Check for new / modified files
|
||||||
@@ -751,7 +875,7 @@ update_ListChanges($)
|
|||||||
} else {
|
} else {
|
||||||
# get list of changes
|
# get list of changes
|
||||||
$ret .= "\nList of last changes:\n";
|
$ret .= "\nList of last changes:\n";
|
||||||
my $changed = GetFileFromURL("$server/$srcdir/CHANGED");
|
my $changed = GetFileFromURL($changedFile);
|
||||||
if (!$changed || $changed =~ m/Error 404/g) {
|
if (!$changed || $changed =~ m/Error 404/g) {
|
||||||
$ret .= "Can't get list of changes from $server";
|
$ret .= "Can't get list of changes from $server";
|
||||||
} else {
|
} else {
|
||||||
@@ -768,9 +892,9 @@ update_ListChanges($)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
sub
|
||||||
update_CheckFhemRelease($$)
|
update_CheckFhemRelease($$$)
|
||||||
{
|
{
|
||||||
my ($force,$srcdir) = @_;
|
my ($force,$srcdir,$BRANCH) = @_;
|
||||||
my $server = $UPDATE{server};
|
my $server = $UPDATE{server};
|
||||||
my $versRemote;
|
my $versRemote;
|
||||||
my $ret = undef;
|
my $ret = undef;
|
||||||
@@ -820,13 +944,19 @@ update_CheckFhemRelease($$)
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
sub
|
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 $modpath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath});
|
||||||
my $moddir = "$modpath/FHEM";
|
my $moddir = "$modpath/FHEM";
|
||||||
return "Can't write $moddir/".$UPDATE{$pack}{control}.": $!" if (!open(FH, ">$moddir/".$UPDATE{$pack}{control}));
|
my $controlsTxt;
|
||||||
Log 5, "update write $moddir/".$UPDATE{$pack}{control};
|
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 %rControl = %$rControl_ref;
|
||||||
my %lControl = %$lControl_ref;
|
my %lControl = %$lControl_ref;
|
||||||
foreach my $f (sort keys %{$rControl{$pack}}) {
|
foreach my $f (sort keys %{$rControl{$pack}}) {
|
||||||
@@ -845,21 +975,21 @@ update_WriteLocalControlFile($$$)
|
|||||||
$file = defined($lControl{$pack}{$f}{file}) ? $lControl{$pack}{$f}{file} :
|
$file = defined($lControl{$pack}{$f}{file}) ? $lControl{$pack}{$f}{file} :
|
||||||
$rControl{$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";
|
print FH "$ctrl $date $size $file\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ctrl eq "DIR") {
|
if ($ctrl eq "DIR") {
|
||||||
Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $file";
|
Log 5, "update $controlsTxt: $ctrl $file";
|
||||||
print FH "$ctrl $file\n";
|
print FH "$ctrl $file\n";
|
||||||
}
|
}
|
||||||
if ($ctrl eq "MOV") {
|
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";
|
print FH "$ctrl $file $move\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ctrl eq "DEL") {
|
if ($ctrl eq "DEL") {
|
||||||
Log 5, "update ".$UPDATE{$pack}{control}.": $ctrl $file";
|
Log 5, "update $controlsTxt: $ctrl $file";
|
||||||
print FH "$ctrl $file\n";
|
print FH "$ctrl $file\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1004,23 +1134,29 @@ update_MakeDirectory($)
|
|||||||
<a name="update"></a>
|
<a name="update"></a>
|
||||||
<h3>update</h3>
|
<h3>update</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<code>update [development|stable] [<file>|check|fhem|full] [force]</code><br>
|
<strong>FHEM update / check for updates:</strong>
|
||||||
|
<br>
|
||||||
|
<code>update [development|stable] [<file|package>] [force]</code><br>
|
||||||
|
<code>update [development|stable] check</code><br>
|
||||||
|
<code>update housekeeping</code><br><br>
|
||||||
|
<strong>Third party package update / check for a package update:</strong>
|
||||||
|
<br>
|
||||||
|
<code>update thirdparty <url> <package> [force]</code><br>
|
||||||
|
<code>update thirdparty <url> <package> check</code><br>
|
||||||
<br>
|
<br>
|
||||||
The installed fhem distribution and its installed extensions (just like the
|
The installed fhem distribution and its installed extensions (just like the
|
||||||
webGUI PGM2) are updated via this command from the online repository. The
|
webGUI PGM2) are updated via this command from the online repository. The
|
||||||
locally installed files will be checked against the online repository and
|
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
|
will be updated in case the files online are in a newer version.
|
||||||
which are used while the update is in progress will be restarted in the new
|
|
||||||
version after the update has finished.
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
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.
|
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.
|
New file structures can also be set up via control command files.
|
||||||
The new update process will exclusively work with the file path which is
|
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
|
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
|
decides whether to use a stable, or a developer-rated version of fhem.
|
||||||
of fhem (experimental is not yet implemented).
|
<strong>stable is not yet implemented</strong>, so an update use always the developer-rated version.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
Furthermore, the use of packages is supported just like in a manual installation
|
Furthermore, the use of packages is supported just like in a manual installation
|
||||||
@@ -1029,6 +1165,46 @@ update_MakeDirectory($)
|
|||||||
used will be updated.
|
used will be updated.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
The update function supports the installation of third-party packages like
|
||||||
|
modules or GUIs that are not part of the FHEM distribution.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<i>Notice for Developers of third-party packages:</i>
|
||||||
|
<br>
|
||||||
|
<i>Further information can be obtained from the file 'docs/LIESMICH.update-thirdparty'.</i>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Examples:
|
||||||
|
<blockquote>Check for new updates:<code><pre>
|
||||||
|
fhem> update check
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>FHEM update:<code><pre>
|
||||||
|
fhem> update
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Force FHEM update (all files are updated!):<code><pre>
|
||||||
|
fhem> update force
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Update a single file:<code><pre>
|
||||||
|
fhem> update 98_foobar.pm
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Search for a filename:<code><pre>
|
||||||
|
fhem> update backup
|
||||||
|
'backup' not found. Did you mean:
|
||||||
|
==> 98_backup.pm
|
||||||
|
nothing to do...
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Update / install a third-party package:<code><pre>
|
||||||
|
fhem> update thirdparty http://domain.tld/path packagename
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Check a third-party package for new updates:<code><pre>
|
||||||
|
fhem> update thirdparty http://domain.tld/path packagename check
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
<a name="updateattr"></a>
|
<a name="updateattr"></a>
|
||||||
<b>Attributes</b>
|
<b>Attributes</b>
|
||||||
@@ -1042,4 +1218,96 @@ update_MakeDirectory($)
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
=end html
|
=end html
|
||||||
|
=begin html_DE
|
||||||
|
|
||||||
|
<a name="update"></a>
|
||||||
|
<h3>update</h3>
|
||||||
|
<ul>
|
||||||
|
<strong>FHEM aktualisieren / auf Aktualisierungen prüfen:</strong>
|
||||||
|
<br>
|
||||||
|
<code>update [development|stable] [<Date|Paket>] [force]</code><br>
|
||||||
|
<code>update [development|stable] check</code><br>
|
||||||
|
<code>update housekeeping</code><br><br>
|
||||||
|
<strong>Aktualisierung eines Fremdpaketes / Fremdpaket auf Aktualisierungen prüfen:</strong>
|
||||||
|
<br>
|
||||||
|
<code>update thirdparty <url> <Paketname> [force]</code><br>
|
||||||
|
<code>update thirdparty <url> <Paketname> check</code><br>
|
||||||
|
<br>
|
||||||
|
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.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
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.
|
||||||
|
<strong>Ein Aktualisierung erfolgt zur Zeit ausschliesslich nur über den
|
||||||
|
Entwicklungs-Zweig (development).</strong>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
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.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
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.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<i>Hinweis für Anbieter von zusätzlichen Paketen:</i>
|
||||||
|
<br>
|
||||||
|
<i>Weiterführende Informationen zur Bereitstellung von Paketen sind der Datei
|
||||||
|
'docs/LIESMICH.update-thirdparty' zu entnehmen.</i>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Beispiele:
|
||||||
|
<blockquote>Auf neue Aktualisierungen prüfen:<code><pre>
|
||||||
|
fhem> update check
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>FHEM aktualisieren:<code><pre>
|
||||||
|
fhem> update
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>FHEM Aktualisierung erzwingen (alle Dateien werden aktualisiert!):<code><pre>
|
||||||
|
fhem> update force
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Eine einzelne Datei aktualisieren:<code><pre>
|
||||||
|
fhem> update 98_foobar.pm
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Nach einem Dateinamen suchen:<code><pre>
|
||||||
|
fhem> update backup
|
||||||
|
'backup' not found. Did you mean:
|
||||||
|
==> 98_backup.pm
|
||||||
|
nothing to do...
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Aktualisierung oder Installation eines Fremdpaketes:<code><pre>
|
||||||
|
fhem> update thirdparty http://domain.tld/path paketname
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<blockquote>Fremdpaket auf neue Aktualisierungen prüfen:<code><pre>
|
||||||
|
fhem> update thirdparty http://domain.tld/path paketname check
|
||||||
|
</pre></code></blockquote>
|
||||||
|
|
||||||
|
<a name="updateattr"></a>
|
||||||
|
<b>Attribute</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#backup_before_update">backup_before_update</a></li><br>
|
||||||
|
|
||||||
|
<li><a href="#exclude_from_update">exclude_from_update</a></li><br>
|
||||||
|
|
||||||
|
<li><a href="#updatebranch">updatebranch</a></li><br>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
=end html_DE
|
||||||
=cut
|
=cut
|
||||||
|
|||||||
145
fhem/docs/LIESMICH.update-thirdparty
Normal file
145
fhem/docs/LIESMICH.update-thirdparty
Normal file
@@ -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_<name>.txt',
|
||||||
|
wobei <name> 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
|
||||||
|
|
||||||
Reference in New Issue
Block a user