Prefer plain pip over git for updating OctoPrint
At least unless we've selected git based tracking over release tracking. This should greatly reduce the likelihood of not being able to update due to some git repository corruption issues, as has happened to some people in the past.
This commit is contained in:
parent
c30e54d75c
commit
79581c390a
12 changed files with 192 additions and 132 deletions
|
|
@ -14,14 +14,14 @@ First Steps
|
|||
|
||||
Out of the box the Software Update Plugin will be able to notify you of any
|
||||
updates that might be available for your OctoPrint installation or any plugins
|
||||
that registered themselves with it. In order to also be able to update
|
||||
your OctoPrint installation, you'll need to configure
|
||||
at least OctoPrint's checkout folder, and you also should
|
||||
configure the restart commands for OctoPrint and the whole server.
|
||||
that registered themselves with it. In order for automatic restarts after updates
|
||||
to work, you should configure the restart commands for OctoPrint and the whole server.
|
||||
|
||||
For configuring the plugin you'll need to go into OctoPrint's Settings Dialog, navigate to the
|
||||
Software Upda.. _section therein and once you are there click on the little wrench icon in the
|
||||
upper right corner.
|
||||
Out of the box the plugin should already be ready to update your OctoPrint installation to current
|
||||
stable release versions, but you can also switch to one of the available release candidate channels
|
||||
or outright git commit tracking via the plugin's configuration dialog. To open this dialog, fire up OctoPrint's
|
||||
Settings Dialog, navigate to the Software Update section therein and once you are there click on the little
|
||||
wrench icon in the upper right corner.
|
||||
|
||||
.. _fig-bundledplugins-softwareupdate-plugin-configuration:
|
||||
.. figure:: ../images/bundledplugins-softwareupdate-plugin-configuration.png
|
||||
|
|
@ -32,31 +32,16 @@ upper right corner.
|
|||
|
||||
There you can adjust the following settings:
|
||||
|
||||
* **OctoPrint checkout folder**: This should be the path to OctoPrint's git checkout folder (``/home/pi/OctoPrint``
|
||||
for OctoPi or `manual installs following the Raspberry Pi setup guide <https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian>`_).
|
||||
This must be set to allow updating from within OctoPrint
|
||||
|
||||
.. note::
|
||||
|
||||
OctoPi releases 0.12.0 and later ship with this already setup for you.
|
||||
|
||||
.. note::
|
||||
|
||||
**OctoPi 0.11.0 users**: Please also take a look at
|
||||
`the note at the very end of this FAQ entry <https://github.com/foosel/OctoPrint/wiki/FAQ#how-can-i-update-the-octoprint-installation-on-my-octopi-image>`_.
|
||||
Due to a little issue in that OctoPi release 0.11.0 you might have to fix
|
||||
the URL your OctoPrint checkout is using for updating. This can easily be
|
||||
done by SSHing into your OctoPi instance and doing this::
|
||||
|
||||
cd ~/OctoPrint
|
||||
git remote set-url origin https://github.com/foosel/OctoPrint.git
|
||||
|
||||
* **OctoPrint version tracking**: Whether you want to track OctoPrint *releases* or every *commit*. Usually you want to
|
||||
select "Release" here which is also the default, unless you are a developer.
|
||||
* **OctoPrint Release Channel**: The release channel of OctoPrint to track for updates. If you only want stable versions,
|
||||
* **OctoPrint Release Channel** (if tracking releases): The release channel of OctoPrint to track for updates. If you only want stable versions,
|
||||
select "Stable" here which is also the default. "Maintenance RCs" will also allow you to update to maintenance release
|
||||
candidates, "Devel RCs" will also allow you to update to development release candidates. If in doubt, leave it at
|
||||
"Stable". `Read more about Release Channels here <https://github.com/foosel/OctoPrint/wiki/Using-Release-Channels>`_.
|
||||
* **OctoPrint checkout folder** (if tracking git commits): This must be the path to OctoPrint's git checkout folder
|
||||
(``/home/pi/OctoPrint`` for OctoPi or `manual installs following the Raspberry Pi setup guide <https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian>`_).
|
||||
Note that since OctoPrint 1.3.6 you will no longer need to set this to be able to update to releases, only if you
|
||||
want to be able to update against some bleeding edge git branch.
|
||||
* **Version cache TTL**: The "time to live" of the cache OctoPrint will use to temporarily persist the version information
|
||||
for the various components registered with the plugin, so that they don't have to be queried from the internet every time
|
||||
you load the page. Defaults to 24h, you usually shouldn't need to change that value.
|
||||
|
|
@ -142,14 +127,13 @@ Configuring the Plugin
|
|||
# "octoprint" is reserved for OctoPrint
|
||||
octoprint:
|
||||
# this defines an version check that will check against releases
|
||||
# published on OctoPrint's Github repository and an update method
|
||||
# utilizing an (included) update script that will be run on
|
||||
# OctoPrint's checkout folder
|
||||
# published on OctoPrint's Github repository and pip as update method
|
||||
# against the release archives on Github - this is the default
|
||||
type: github_release
|
||||
user: foosel
|
||||
repo: OctoPrint
|
||||
update_script: '{python} "/path/to/octoprint-update.py" --python="{python}" "{folder}" "{target}"'
|
||||
update_folder: /path/to/octoprint/checkout/folder
|
||||
method: pip
|
||||
pip: 'https://github.com/foosel/OctoPrint/archive/{target_version}.zip'
|
||||
|
||||
# further checks may be define here
|
||||
|
||||
|
|
@ -249,6 +233,32 @@ Update methods
|
|||
:ref:`hook <sec-bundledplugins-softwareupdate-hooks>`. A python callable
|
||||
which performs the update, see below for details.
|
||||
|
||||
.. note::
|
||||
|
||||
To allow default configurations for multiple update methods, if more than one of
|
||||
the above update method specific settings is set the one to use can be selected
|
||||
by setting the property ``method`` to the method specific setting in question.
|
||||
|
||||
**Example**
|
||||
|
||||
The following example defines both ``pip`` and ``update_script``. By setting to
|
||||
``method`` to ``pip``, the Software Update plugin is instructed to use that as
|
||||
update method.
|
||||
|
||||
.. code-block::
|
||||
|
||||
plugins:
|
||||
softwareupdate:
|
||||
checks:
|
||||
octoprint:
|
||||
type: github_release
|
||||
user: foosel
|
||||
repo: OctoPrint
|
||||
method: pip
|
||||
pip: 'https://github.com/foosel/OctoPrint/archive/{target_version}.zip'
|
||||
update_script: '{python} "/path/to/octoprint-update.py" --python="{python}" "{folder}" "{target}"'
|
||||
checkout_folder: /path/to/octoprint/checkout/folder
|
||||
|
||||
.. _sec-bundledplugins-softwareupdate-configuration-patterns:
|
||||
|
||||
Common configuration patterns
|
||||
|
|
@ -268,6 +278,7 @@ plugin itself):
|
|||
user: foosel
|
||||
repo: OctoPrint
|
||||
branch: devel
|
||||
method: update_script
|
||||
update_folder: /home/pi/OctoPrint
|
||||
|
||||
Plugin installed via pip and hosted on Github under
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 24 KiB |
|
|
@ -41,6 +41,8 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
octoprint.plugin.EventHandlerPlugin):
|
||||
|
||||
COMMIT_TRACKING_TYPES = ("github_commit", "bitbucket_commit")
|
||||
|
||||
DATA_FORMAT_VERSION = "v2"
|
||||
|
||||
def __init__(self):
|
||||
self._update_in_progress = False
|
||||
|
|
@ -216,13 +218,18 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
|
||||
def get_settings_defaults(self):
|
||||
update_script = os.path.join(self._basefolder, "scripts", "update-octoprint.py")
|
||||
default_update_script = "{{python}} \"{update_script}\" --branch={{branch}} " \
|
||||
"--force={{force}} \"{{folder}}\" {{target}}".format(update_script=update_script)
|
||||
|
||||
return {
|
||||
"checks": {
|
||||
"octoprint": {
|
||||
"type": "github_release",
|
||||
"user": "foosel",
|
||||
"repo": "OctoPrint",
|
||||
"update_script": "{{python}} \"{update_script}\" --branch={{branch}} --force={{force}} \"{{folder}}\" {{target}}".format(update_script=update_script),
|
||||
"method": "pip",
|
||||
"pip": "https://github.com/foosel/OctoPrint/archive/{target_version}.zip",
|
||||
"update_script": default_update_script,
|
||||
"restart": "octoprint",
|
||||
"stable_branch": dict(branch="master", commitish=["master"], name="Stable"),
|
||||
"prerelease_branches": [dict(branch="rc/maintenance",
|
||||
|
|
@ -302,12 +309,13 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
if "octoprint" in checks:
|
||||
check = checks["octoprint"]
|
||||
update_type = check.get("type", None)
|
||||
update_method = self._get_update_method("octoprint", check)
|
||||
checkout_folder = check.get("checkout_folder", None)
|
||||
update_folder = check.get("update_folder", None)
|
||||
prerelease = check.get("prerelease", False)
|
||||
prerelease_channel = check.get("prerelease_channel", None)
|
||||
else:
|
||||
update_type = checkout_folder = update_folder = prerelease_channel = None
|
||||
update_type = update_method = checkout_folder = update_folder = prerelease_channel = None
|
||||
prerelease = False
|
||||
|
||||
defaults = dict(
|
||||
|
|
@ -315,6 +323,7 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
checks=dict(
|
||||
octoprint=dict(
|
||||
type=update_type,
|
||||
method=update_method,
|
||||
checkout_folder=checkout_folder,
|
||||
update_folder=update_folder,
|
||||
prerelease=prerelease,
|
||||
|
|
@ -332,10 +341,30 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
self._settings.set(["checks", "octoprint", "update_folder"], None, defaults=defaults, force=True)
|
||||
updated_octoprint_check_config = True
|
||||
|
||||
if "octoprint_type" in data and data["octoprint_type"] in ("github_release", "git_commit"):
|
||||
self._settings.set(["checks", "octoprint", "type"], data["octoprint_type"], defaults=defaults, force=True)
|
||||
updated_octoprint_check_config = True
|
||||
if "octoprint_type" in data:
|
||||
octoprint_type = data["octoprint_type"]
|
||||
|
||||
if octoprint_type == "github_release":
|
||||
self._settings.set(["checks", "octoprint", "type"], octoprint_type, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "method"], "pip", defaults=defaults, force=True)
|
||||
updated_octoprint_check_config = True
|
||||
|
||||
elif octoprint_type == "git_commit":
|
||||
self._settings.set(["checks", "octoprint", "type"], octoprint_type, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "method"], "update_script", defaults=defaults, force=True)
|
||||
updated_octoprint_check_config = True
|
||||
|
||||
if "octoprint_release_channel" in data:
|
||||
prerelease_branches = self._settings.get(["checks", "octoprint", "prerelease_branches"])
|
||||
if prerelease_branches and data["octoprint_release_channel"] in [x["branch"] for x in prerelease_branches]:
|
||||
self._settings.set(["checks", "octoprint", "prerelease"], True, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "prerelease_channel"], data["octoprint_release_channel"],
|
||||
defaults=defaults, force=True)
|
||||
else:
|
||||
self._settings.set(["checks", "octoprint", "prerelease"], False, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "prerelease_channel"], None, defaults=defaults, force=True)
|
||||
updated_octoprint_check_config = True
|
||||
|
||||
if updated_octoprint_check_config:
|
||||
self._refresh_configured_checks = True
|
||||
try:
|
||||
|
|
@ -344,22 +373,23 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
pass
|
||||
self._version_cache_dirty = True
|
||||
|
||||
if "octoprint_release_channel" in data:
|
||||
prerelease_branches = self._settings.get(["checks", "octoprint", "prerelease_branches"])
|
||||
if prerelease_branches and data["octoprint_release_channel"] in [x["branch"] for x in prerelease_branches]:
|
||||
self._settings.set(["checks", "octoprint", "prerelease"], True, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "prerelease_channel"], data["octoprint_release_channel"], defaults=defaults, force=True)
|
||||
self._refresh_configured_checks = True
|
||||
else:
|
||||
self._settings.set(["checks", "octoprint", "prerelease"], False, defaults=defaults, force=True)
|
||||
self._settings.set(["checks", "octoprint", "prerelease_channel"], None, defaults=defaults, force=True)
|
||||
self._refresh_configured_checks = True
|
||||
|
||||
def get_settings_version(self):
|
||||
return 5
|
||||
return 6
|
||||
|
||||
def on_settings_migrate(self, target, current=None):
|
||||
|
||||
if current is None or current < 6:
|
||||
# up until & including config version 5 we didn't set the method parameter for the octoprint check
|
||||
# configuration
|
||||
|
||||
configured_checks = self._settings.get(["checks"], incl_defaults=False)
|
||||
if configured_checks is not None and "octoprint" in configured_checks:
|
||||
octoprint_check = dict(configured_checks["octoprint"])
|
||||
|
||||
if not "method" in octoprint_check and octoprint_check.get("type") == "git_commit":
|
||||
defaults = dict(plugins=dict(softwareupdate=dict(checks=dict(octoprint=dict(method="pip")))))
|
||||
self._settings.set(["checks", "octoprint", "method"], "update_script", defaults=defaults)
|
||||
|
||||
if current == 4:
|
||||
# config version 4 didn't correctly remove the old settings for octoprint_restart_command
|
||||
# and environment_restart_command
|
||||
|
|
@ -504,6 +534,7 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
hash.update(",".join(targets))
|
||||
hash.update(str(self._version_cache_timestamp))
|
||||
hash.update(str(self._connectivity_checker.online))
|
||||
hash.update(self.DATA_FORMAT_VERSION)
|
||||
return hash.hexdigest()
|
||||
|
||||
def condition():
|
||||
|
|
@ -563,7 +594,7 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
checks = self._get_configured_checks()
|
||||
check = checks.get("octoprint", None)
|
||||
checkout_folder = self._get_octoprint_checkout_folder(checks=checks)
|
||||
return check and "update_script" in check and not checkout_folder
|
||||
return check and "method" in check and check["method"] == "update_script" and not checkout_folder
|
||||
|
||||
##~~ EventHandlerPlugin API
|
||||
|
||||
|
|
@ -667,6 +698,9 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
releaseNotes=release_notes,
|
||||
online=target_online,
|
||||
error=target_error)
|
||||
|
||||
if target == "octoprint" and "released_version" in populated_check:
|
||||
information[target]["released_version"] = populated_check["released_version"]
|
||||
|
||||
if self._version_cache_dirty:
|
||||
self._save_version_cache()
|
||||
|
|
@ -989,24 +1023,22 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
# we compare versions fully, not just the base so that we see a difference
|
||||
# between RCs + stable for the same version release
|
||||
result["force_base"] = False
|
||||
|
||||
if check.get("prerelease", None):
|
||||
# we are tracking prereleases => we want to be on the correct prerelease channel/branch
|
||||
channel = check.get("prerelease_channel", None)
|
||||
if channel:
|
||||
# if we have a release channel, we also set our update_branch here to our release channel
|
||||
# in case it's not already set
|
||||
result["update_branch"] = check.get("update_branch", channel)
|
||||
|
||||
else:
|
||||
# we are not tracking prereleases, but aren't on the stable branch either => switch back
|
||||
# to stable branch on update
|
||||
result["update_branch"] = check.get("update_branch", stable_branch)
|
||||
|
||||
if check.get("update_script", None):
|
||||
# if we are using the update_script, we need to set our update_branch
|
||||
|
||||
if check.get("prerelease", None):
|
||||
# we are tracking prereleases => we want to be on the correct prerelease channel/branch
|
||||
channel = check.get("prerelease_channel", None)
|
||||
if channel:
|
||||
# if we have a release channel, we also set our update_branch here to our release channel
|
||||
# in case it's not already set
|
||||
result["update_branch"] = check.get("update_branch", channel)
|
||||
|
||||
else:
|
||||
# we are not tracking prereleases, but aren't on the stable branch either => switch back
|
||||
# to stable branch on update
|
||||
result["update_branch"] = check.get("update_branch", stable_branch)
|
||||
|
||||
# we also force an exact version
|
||||
# we force an exact version
|
||||
result["force_exact_version"] = True
|
||||
|
||||
if BRANCH != result.get("prerelease_channel"):
|
||||
|
|
@ -1017,6 +1049,10 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
|
|||
# branch of the release channel - unequality means we might have to handle
|
||||
# a downgrade
|
||||
result["release_compare"] = "python_unequal"
|
||||
|
||||
elif check.get("pip", None):
|
||||
# we force python unequality check for pip installs, to be able to downgrade
|
||||
result["release_compare"] = "python_unequal"
|
||||
|
||||
else:
|
||||
result["displayName"] = to_unicode(check.get("displayName"), errors="replace")
|
||||
|
|
|
|||
|
|
@ -108,8 +108,15 @@ $(function() {
|
|||
|
||||
self.checking = ko.observable(false);
|
||||
|
||||
self.octoprintUnconfigured = ko.observable();
|
||||
self.octoprintUnreleased = ko.observable();
|
||||
self.octoprintReleasedVersion = ko.observable();
|
||||
|
||||
self.octoprintUnconfigured = ko.pureComputed(function() {
|
||||
return self.error_checkoutFolder();
|
||||
});
|
||||
self.octoprintUnreleased = ko.pureComputed(function() {
|
||||
return self.settings.settings.plugins.softwareupdate.octoprint_type() === "github_release"
|
||||
&& !self.octoprintReleasedVersion();
|
||||
});
|
||||
|
||||
self.cacheTimestamp = ko.observable();
|
||||
self.cacheTimestampText = ko.pureComputed(function() {
|
||||
|
|
@ -120,9 +127,18 @@ $(function() {
|
|||
self.config_notifyUsers = ko.observable();
|
||||
self.config_checkoutFolder = ko.observable();
|
||||
self.config_checkType = ko.observable();
|
||||
self.config_updateMethod = ko.observable();
|
||||
self.config_releaseChannel = ko.observable();
|
||||
|
||||
self.error_checkoutFolder = ko.pureComputed(function() {
|
||||
return self.config_checkType() === "git_commit"
|
||||
&& (!self.config_checkoutFolder() || self.config_checkoutFolder().trim() === '');
|
||||
});
|
||||
|
||||
self.enable_configSave = ko.pureComputed(function() {
|
||||
return self.config_checkType() === "github_release"
|
||||
|| (self.config_checkType() === "git_commit" && !self.error_checkoutFolder());
|
||||
});
|
||||
|
||||
self.configurationDialog = undefined;
|
||||
self.confirmationDialog = undefined;
|
||||
self._updateClicked = false;
|
||||
|
|
@ -137,8 +153,8 @@ $(function() {
|
|||
{
|
||||
"name": function(a, b) {
|
||||
// sorts ascending, puts octoprint first
|
||||
if (a.key.toLocaleLowerCase() == "octoprint") return -1;
|
||||
if (b.key.toLocaleLowerCase() == "octoprint") return 1;
|
||||
if (a.key.toLocaleLowerCase() === "octoprint") return -1;
|
||||
if (b.key.toLocaleLowerCase() === "octoprint") return 1;
|
||||
|
||||
if (a.displayName.toLocaleLowerCase() < b.displayName.toLocaleLowerCase()) return -1;
|
||||
if (a.displayName.toLocaleLowerCase() > b.displayName.toLocaleLowerCase()) return 1;
|
||||
|
|
@ -211,9 +227,9 @@ $(function() {
|
|||
softwareupdate: {
|
||||
cache_ttl: parseInt(self.config_cacheTtl()),
|
||||
notify_users: self.config_notifyUsers(),
|
||||
octoprint_checkout_folder: self.config_checkoutFolder(),
|
||||
octoprint_type: self.config_checkType(),
|
||||
octoprint_release_channel: self.config_releaseChannel()
|
||||
octoprint_release_channel: self.config_releaseChannel(),
|
||||
octoprint_checkout_folder: self.config_checkoutFolder()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -231,15 +247,8 @@ $(function() {
|
|||
};
|
||||
|
||||
self._copyConfig = function() {
|
||||
var updateMethod = self.settings.settings.plugins.softwareupdate.octoprint_method();
|
||||
|
||||
var availableCheckTypes = [];
|
||||
if (updateMethod == "update_script" || updateMethod == "python") {
|
||||
availableCheckTypes = [{"key": "github_release", "name": gettext("Release")},
|
||||
var availableCheckTypes = [{"key": "github_release", "name": gettext("Release")},
|
||||
{"key": "git_commit", "name": gettext("Commit")}];
|
||||
} else {
|
||||
availableCheckTypes = [];
|
||||
}
|
||||
self.config_availableCheckTypes(availableCheckTypes);
|
||||
|
||||
var availableReleaseChannels = [];
|
||||
|
|
@ -248,12 +257,12 @@ $(function() {
|
|||
});
|
||||
self.config_availableReleaseChannels(availableReleaseChannels);
|
||||
|
||||
self.config_updateMethod(updateMethod);
|
||||
self.config_cacheTtl(self.settings.settings.plugins.softwareupdate.cache_ttl());
|
||||
self.config_notifyUsers(self.settings.settings.plugins.softwareupdate.notify_users());
|
||||
self.config_checkoutFolder(self.settings.settings.plugins.softwareupdate.octoprint_checkout_folder());
|
||||
|
||||
self.config_checkType(self.settings.settings.plugins.softwareupdate.octoprint_type());
|
||||
self.config_releaseChannel(self.settings.settings.plugins.softwareupdate.octoprint_release_channel());
|
||||
self.config_checkoutFolder(self.settings.settings.plugins.softwareupdate.octoprint_checkout_folder());
|
||||
};
|
||||
|
||||
self._copyConfigBack = function() {
|
||||
|
|
@ -268,13 +277,13 @@ $(function() {
|
|||
_.each(data.information, function(value, key) {
|
||||
value["key"] = key;
|
||||
|
||||
if (!value.hasOwnProperty("displayName") || value.displayName == "") {
|
||||
if (!value.hasOwnProperty("displayName") || value.displayName === "") {
|
||||
value.displayName = value.key;
|
||||
}
|
||||
if (!value.hasOwnProperty("displayVersion") || value.displayVersion == "") {
|
||||
if (!value.hasOwnProperty("displayVersion") || value.displayVersion === "") {
|
||||
value.displayVersion = value.information.local.name;
|
||||
}
|
||||
if (!value.hasOwnProperty("releaseNotes") || value.releaseNotes == "") {
|
||||
if (!value.hasOwnProperty("releaseNotes") || value.releaseNotes === "") {
|
||||
value.releaseNotes = undefined;
|
||||
}
|
||||
|
||||
|
|
@ -292,27 +301,11 @@ $(function() {
|
|||
self.versions.updateItems(versions);
|
||||
|
||||
var octoprint = data.information["octoprint"];
|
||||
if (octoprint && octoprint.hasOwnProperty("check")) {
|
||||
var check = octoprint.check;
|
||||
if (check["released_version"] === false && check["type"] == "github_release") {
|
||||
self.octoprintUnreleased(true);
|
||||
} else {
|
||||
self.octoprintUnreleased(false);
|
||||
}
|
||||
|
||||
var checkoutFolder = (check["checkout_folder"] || "").trim();
|
||||
var updateFolder = (check["update_folder"] || "").trim();
|
||||
var needsFolder = check["update_script"] || false;
|
||||
if (needsFolder && checkoutFolder == "" && updateFolder == "") {
|
||||
self.octoprintUnconfigured(true);
|
||||
} else {
|
||||
self.octoprintUnconfigured(false);
|
||||
}
|
||||
}
|
||||
self.octoprintReleasedVersion(!octoprint || octoprint.released_version);
|
||||
|
||||
if (!self.loginState.isAdmin() && !self.settings.settings.plugins.softwareupdate.notify_users()) return;
|
||||
|
||||
if (data.status == "updateAvailable" || data.status == "updatePossible") {
|
||||
if (data.status === "updateAvailable" || data.status === "updatePossible") {
|
||||
var text = "<div class='softwareupdate_notification'>" + gettext("There are updates available for the following components:");
|
||||
|
||||
text += "<ul class='fa-ul'>";
|
||||
|
|
@ -343,7 +336,7 @@ $(function() {
|
|||
var eventListeners = {};
|
||||
|
||||
var singleButtonNotify = false;
|
||||
if (data.status == "updatePossible" && self.loginState.isAdmin()) {
|
||||
if (data.status === "updatePossible" && self.loginState.isAdmin()) {
|
||||
// if update is possible and user is admin, add action buttons for ignore and update
|
||||
options["confirm"] = {
|
||||
confirm: true,
|
||||
|
|
@ -391,7 +384,7 @@ $(function() {
|
|||
if ((ignoreSeen || !self._hasNotificationBeenSeen(data.information)) && !OctoPrint.coreui.wizardOpen) {
|
||||
self._showPopup(options, eventListeners, singleButtonNotify);
|
||||
}
|
||||
} else if (data.status == "current") {
|
||||
} else if (data.status === "current") {
|
||||
if (showIfNothingNew) {
|
||||
self._showPopup({
|
||||
title: gettext("Everything is up-to-date"),
|
||||
|
|
@ -473,7 +466,7 @@ $(function() {
|
|||
if (!Modernizr.localstorage)
|
||||
return false;
|
||||
|
||||
if (localStorage["plugin.softwareupdate.seen_information"] == undefined)
|
||||
if (localStorage["plugin.softwareupdate.seen_information"] === undefined)
|
||||
return false;
|
||||
|
||||
var knownData = JSON.parse(localStorage["plugin.softwareupdate.seen_information"]);
|
||||
|
|
@ -489,7 +482,7 @@ $(function() {
|
|||
|
||||
var hasBeenSeen = true;
|
||||
_.each(freshData, function(value, key) {
|
||||
if (!_.has(userData, key) || userData[key] != freshData[key]) {
|
||||
if (!_.has(userData, key) || userData[key] !== freshData[key]) {
|
||||
hasBeenSeen = false;
|
||||
}
|
||||
});
|
||||
|
|
@ -610,10 +603,10 @@ $(function() {
|
|||
};
|
||||
|
||||
self.onBeforeWizardTabChange = function(next, current) {
|
||||
if (next && _.startsWith(next, "wizard_plugin_softwareupdate")) {
|
||||
if (next && next === "#wizard_plugin_softwareupdate") {
|
||||
// switching to the plugin wizard tab
|
||||
self._copyConfig();
|
||||
} else if (current && _.startsWith(current, "wizard_plugin_softwareupdate")) {
|
||||
} else if (current && current === "#wizard_plugin_softwareupdate") {
|
||||
// switching away from the plugin wizard tab
|
||||
self._copyConfigBack();
|
||||
}
|
||||
|
|
@ -658,7 +651,7 @@ $(function() {
|
|||
};
|
||||
|
||||
self.onDataUpdaterPluginMessage = function(plugin, data) {
|
||||
if (plugin != "softwareupdate") {
|
||||
if (plugin !== "softwareupdate") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -749,7 +742,7 @@ $(function() {
|
|||
|
||||
restartType = messageData.restart_type;
|
||||
text = gettext("The update finished successfully, please restart OctoPrint now.");
|
||||
if (restartType == "environment") {
|
||||
if (restartType === "environment") {
|
||||
text = gettext("The update finished successfully, please reboot the server now.");
|
||||
}
|
||||
|
||||
|
|
@ -770,7 +763,7 @@ $(function() {
|
|||
case "restart_failed": {
|
||||
restartType = messageData.restart_type;
|
||||
text = gettext("Restarting OctoPrint failed, please restart it manually. You might also want to consult the log file on what went wrong here.");
|
||||
if (restartType == "environment") {
|
||||
if (restartType === "environment") {
|
||||
text = gettext("Rebooting the server failed, please reboot it manually. You might also want to consult the log file on what went wrong here.");
|
||||
}
|
||||
|
||||
|
|
@ -827,7 +820,7 @@ $(function() {
|
|||
}
|
||||
}
|
||||
|
||||
if (options != undefined) {
|
||||
if (options !== undefined) {
|
||||
self._showPopup(options);
|
||||
}
|
||||
};
|
||||
|
|
@ -837,7 +830,7 @@ $(function() {
|
|||
"'.*?' does not exist -- can't clean it"];
|
||||
self._forcedStdoutLine = new RegExp(self._forcedStdoutPatterns.join("|"));
|
||||
self._preprocessLine = function(line) {
|
||||
if (line.stream == "stderr" && line.line.match(self._forcedStdoutLine)) {
|
||||
if (line.stream === "stderr" && line.line.match(self._forcedStdoutLine)) {
|
||||
line.stream = "stdout";
|
||||
}
|
||||
return line;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<div class="control-group" data-bind="visible: config_updateMethod() == 'update_script' || config_updateMethod() == 'python_updater'">
|
||||
<div class="control-group" data-bind="visible: config_checkType() === 'git_commit', css: {error: error_checkoutFolder}">
|
||||
<label class="control-label">{{ _('OctoPrint checkout folder') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: config_checkoutFolder">
|
||||
<span class="help-block" data-bind="visible: error_checkoutFolder">{{ _('This needs to be set if you select commit based version tracking.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="control-group" data-bind="visible: config_availableCheckTypes().length > 0 && config_checkType() == 'github_release'">
|
||||
<div class="control-group" data-bind="visible: config_availableReleaseChannels().length && config_checkType() === 'github_release'">
|
||||
<label class="control-label">{{ _('OctoPrint Release Channel') }}</label>
|
||||
<div class="controls">
|
||||
<select data-bind="value: config_releaseChannel, options: config_availableReleaseChannels, optionsText: 'name', optionsValue: 'key'"></select>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="control-group" data-bind="visible: config_availableCheckTypes().length > 0">
|
||||
<div class="control-group" data-bind="visible: config_availableCheckTypes().length > 1">
|
||||
<label class="control-label">{{ _('OctoPrint version tracking') }}</label>
|
||||
<div class="controls">
|
||||
<select data-bind="value: config_checkType, options: config_availableCheckTypes, optionsText: 'name', optionsValue: 'key'"></select>
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal">
|
||||
{% include "snippets/plugins/softwareupdate/checkoutFolder.jinja2" %}
|
||||
{% include "snippets/plugins/softwareupdate/versionTracking.jinja2" %}
|
||||
{% include "snippets/plugins/softwareupdate/checkoutFolder.jinja2" %}
|
||||
{% include "snippets/plugins/softwareupdate/releaseChannel.jinja2" %}
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Version cache TTL') }}</label>
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Cancel') }}</button>
|
||||
<button class="btn btn-primary" data-bind="click: savePluginSettings" aria-hidden="true">{{ _('Save') }}</button>
|
||||
<button class="btn btn-primary" data-bind="enable: enable_configSave, css: {disabled: !enable_configSave()}, click: savePluginSettings" aria-hidden="true">{{ _('Save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
<h3>{{ _('Software Update') }}</h3>
|
||||
|
||||
{% trans %}<p>
|
||||
OctoPrint can update itself via <code>git</code>, but it needs to know its checkout folder and the way
|
||||
it should track available updates in order to be able to do that. You can configure that here.
|
||||
By default, OctoPrint will update itself via <code>pip</code> to published releases. OctoPrint can
|
||||
also update itself via <code>git</code> to arbitrary development branches you need to check out manually.
|
||||
If you want to do that though it needs to know its checkout folder. You can configure that here.
|
||||
</p>{% endtrans %}
|
||||
|
||||
<form class="form-horizontal">
|
||||
{% include "snippets/plugins/softwareupdate/checkoutFolder.jinja2" %}
|
||||
{% include "snippets/plugins/softwareupdate/versionTracking.jinja2" %}
|
||||
{% include "snippets/plugins/softwareupdate/checkoutFolder.jinja2" %}
|
||||
</form>
|
||||
|
||||
{% trans %}<p>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ from .. import exceptions
|
|||
logger = logging.getLogger("octoprint.plugins.softwareupdate.updaters.pip")
|
||||
console_logger = logging.getLogger("octoprint.plugins.softwareupdate.updaters.pip.console")
|
||||
|
||||
_ALREADY_INSTALLED = "Requirement already satisfied (use --upgrade to upgrade)"
|
||||
|
||||
_pip_callers = dict()
|
||||
_pip_version_dependency_links = pkg_resources.parse_version("1.5")
|
||||
|
||||
|
|
@ -35,7 +37,7 @@ def _get_pip_caller(command=None):
|
|||
|
||||
return _pip_callers[key]
|
||||
|
||||
def perform_update(target, check, target_version, log_cb=None, online=True):
|
||||
def perform_update(target, check, target_version, log_cb=None, online=True, force=False):
|
||||
pip_command = None
|
||||
if "pip_command" in check:
|
||||
pip_command = check["pip_command"]
|
||||
|
|
@ -66,10 +68,10 @@ def perform_update(target, check, target_version, log_cb=None, online=True):
|
|||
pip_caller.on_log_stdout = _log_stdout
|
||||
pip_caller.on_log_stderr = _log_stderr
|
||||
|
||||
install_arg = check["pip"].format(target_version=target_version)
|
||||
install_arg = check["pip"].format(target_version=target_version, target=target_version)
|
||||
|
||||
logger.debug(u"Target: %s, executing pip install %s" % (target, install_arg))
|
||||
pip_args = ["install", check["pip"].format(target_version=target_version, target=target_version)]
|
||||
pip_args = ["install", install_arg]
|
||||
|
||||
if "dependency_links" in check and check["dependency_links"]:
|
||||
pip_args += ["--process-dependency-links"]
|
||||
|
|
@ -77,12 +79,17 @@ def perform_update(target, check, target_version, log_cb=None, online=True):
|
|||
returncode, stdout, stderr = pip_caller.execute(*pip_args)
|
||||
if returncode != 0:
|
||||
raise exceptions.UpdateError("Error while executing pip install", (stdout, stderr))
|
||||
|
||||
if not force and any(map(lambda x: x.strip().startswith(_ALREADY_INSTALLED) and (install_arg in x or install_arg in x.lower()), stdout)):
|
||||
logger.debug(u"Looks like we were already installed in this version. Forcing a reinstall.")
|
||||
force = True
|
||||
|
||||
logger.debug(u"Target: %s, executing pip install %s --ignore-reinstalled --force-reinstall --no-deps" % (target, install_arg))
|
||||
pip_args += ["--ignore-installed", "--force-reinstall", "--no-deps"]
|
||||
|
||||
returncode, stdout, stderr = pip_caller.execute(*pip_args)
|
||||
if returncode != 0:
|
||||
raise exceptions.UpdateError("Error while executing pip install --force-reinstall", (stdout, stderr))
|
||||
if force:
|
||||
logger.debug(u"Target: %s, executing pip install %s --ignore-reinstalled --force-reinstall --no-deps" % (target, install_arg))
|
||||
pip_args += ["--ignore-installed", "--force-reinstall", "--no-deps"]
|
||||
|
||||
returncode, stdout, stderr = pip_caller.execute(*pip_args)
|
||||
if returncode != 0:
|
||||
raise exceptions.UpdateError("Error while executing pip install --force-reinstall", (stdout, stderr))
|
||||
|
||||
return "ok"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ $(function() {
|
|||
}
|
||||
|
||||
callViewModels(self.allViewModels, "onWizardShow");
|
||||
|
||||
callViewModels(self.allViewModels, "onBeforeWizardTabChange", [OCTOPRINT_INITIAL_WIZARD, undefined]);
|
||||
callViewModels(self.allViewModels, "onAfterWizardTabChange", [OCTOPRINT_INITIAL_WIZARD]);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,4 +44,12 @@
|
|||
{% else %}
|
||||
var OCTOPRINT_INITIAL_TAB = undefined;
|
||||
{% endif %}
|
||||
|
||||
{% if templates.wizard and templates.wizard.order %}
|
||||
{% set first_tab = templates.wizard.order[0] %}
|
||||
{% set entry, data = templates.wizard.entries[first_tab] %}
|
||||
var OCTOPRINT_INITIAL_WIZARD = "#{{ data._div }}";
|
||||
{% else %}
|
||||
var OCTOPRINT_INITIAL_WIZARD = undefined;
|
||||
{% endif %}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue