Addon Manager: Allow primary branch name change
This commit is contained in:
committed by
Chris Hennes
parent
430b6c75cb
commit
39043cf176
@@ -192,6 +192,7 @@ class Addon:
|
||||
self.macro = None # Bridge to Gaël Écorchard's macro management class
|
||||
self.updated_timestamp = None
|
||||
self.installed_version = None
|
||||
self.installed_metadata = None
|
||||
|
||||
# Each repo is also a node in a directed dependency graph (referenced by name so
|
||||
# they can be serialized):
|
||||
@@ -254,6 +255,8 @@ class Addon:
|
||||
if os.path.isfile(cached_package_xml_file):
|
||||
instance.load_metadata_file(cached_package_xml_file)
|
||||
|
||||
instance._load_installed_metadata()
|
||||
|
||||
if "requires" in cache_dict:
|
||||
instance.requires = set(cache_dict["requires"])
|
||||
instance.blocks = set(cache_dict["blocks"])
|
||||
@@ -293,6 +296,14 @@ class Addon:
|
||||
else:
|
||||
fci.Console.PrintLog(f"Internal error: {file} does not exist")
|
||||
|
||||
def _load_installed_metadata(self) -> None:
|
||||
# If it is actually installed, there is a SECOND metadata file, in the actual installation,
|
||||
# that may not match the cached one if the Addon has not been updated but the cache has.
|
||||
mod_dir = os.path.join(self.mod_directory, self.name)
|
||||
installed_metadata_path = os.path.join(mod_dir, "package.xml")
|
||||
if os.path.isfile(installed_metadata_path):
|
||||
self.installed_metadata = MetadataReader.from_file(installed_metadata_path)
|
||||
|
||||
def set_metadata(self, metadata: Metadata) -> None:
|
||||
"""Set the given metadata object as this object's metadata, updating the
|
||||
object's display name and package type information to match, as well as
|
||||
@@ -683,9 +694,7 @@ class Addon:
|
||||
filename, extension = os.path.splitext(current_file)
|
||||
if extension == ".py":
|
||||
wb_classname = self._find_classname_in_file(current_file)
|
||||
print(f"Current file: {current_file} ")
|
||||
if wb_classname:
|
||||
print(f"Found name {wb_classname} \n")
|
||||
return wb_classname
|
||||
return ""
|
||||
|
||||
|
||||
@@ -387,6 +387,30 @@ class GitManager:
|
||||
result_dict[author]["count"] += 1
|
||||
return result_dict
|
||||
|
||||
def migrate_branch(self, local_path: str, old_branch: str, new_branch: str) -> None:
|
||||
"""Rename a branch (used when the remote branch name changed). Assumes that "origin"
|
||||
exists."""
|
||||
old_dir = os.getcwd()
|
||||
os.chdir(local_path)
|
||||
try:
|
||||
self._synchronous_call_git(["branch", "-m", old_branch, new_branch])
|
||||
self._synchronous_call_git(["fetch", "origin"])
|
||||
self._synchronous_call_git(["branch", "--unset-upstream"])
|
||||
self._synchronous_call_git(["branch", f"--set-upstream-to=origin/{new_branch}"])
|
||||
self._synchronous_call_git(["pull"])
|
||||
except GitFailed as e:
|
||||
fci.Console.PrintWarning(
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"Git branch rename failed with the following message:",
|
||||
)
|
||||
+ str(e)
|
||||
+ "\n"
|
||||
)
|
||||
os.chdir(old_dir)
|
||||
raise e
|
||||
os.chdir(old_dir)
|
||||
|
||||
def _find_git(self):
|
||||
# Find git. In preference order
|
||||
# A) The value of the GitExecutable user preference
|
||||
|
||||
@@ -40,6 +40,7 @@ from PySide import QtCore
|
||||
|
||||
from Addon import Addon
|
||||
import addonmanager_utilities as utils
|
||||
from addonmanager_metadata import get_branch_from_metadata
|
||||
from addonmanager_git import initialize_git, GitFailed
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
@@ -281,7 +282,12 @@ class AddonInstaller(QtCore.QObject):
|
||||
install_path = os.path.join(self.installation_path, self.addon_to_install.name)
|
||||
try:
|
||||
if os.path.isdir(install_path):
|
||||
self.git_manager.update(install_path)
|
||||
old_branch = get_branch_from_metadata(self.addon_to_install.installed_metadata)
|
||||
new_branch = get_branch_from_metadata(self.addon_to_install.metadata)
|
||||
if old_branch != new_branch:
|
||||
self.git_manager.migrate_branch(install_path, old_branch, new_branch)
|
||||
else:
|
||||
self.git_manager.update(install_path)
|
||||
else:
|
||||
self.git_manager.clone(self.addon_to_install.url, install_path)
|
||||
self.git_manager.checkout(install_path, self.addon_to_install.branch)
|
||||
|
||||
@@ -234,6 +234,13 @@ def get_first_supported_freecad_version(metadata: Metadata) -> Optional[Version]
|
||||
return current_earliest
|
||||
|
||||
|
||||
def get_branch_from_metadata(metadata: Metadata) -> str:
|
||||
for url in metadata.url:
|
||||
if url.type == UrlType.repository:
|
||||
return url.branch
|
||||
return "master" # Legacy default
|
||||
|
||||
|
||||
class MetadataReader:
|
||||
"""Read metadata XML data and construct a Metadata object"""
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ from addonmanager_macro import Macro
|
||||
from Addon import Addon
|
||||
import NetworkManager
|
||||
from addonmanager_git import initialize_git, GitFailed
|
||||
from addonmanager_metadata import MetadataReader
|
||||
from addonmanager_metadata import MetadataReader, get_branch_from_metadata
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
@@ -193,8 +193,8 @@ class CreateAddonListWorker(QtCore.QThread):
|
||||
repo = Addon(name, addon["url"], state, addon["branch"])
|
||||
md_file = os.path.join(addondir, "package.xml")
|
||||
if os.path.isfile(md_file):
|
||||
repo.load_metadata_file(md_file)
|
||||
repo.installed_version = repo.metadata.version
|
||||
repo.installed_metadata = MetadataReader.from_file(md_file)
|
||||
repo.installed_version = repo.installed_metadata.version
|
||||
repo.updated_timestamp = os.path.getmtime(md_file)
|
||||
repo.verify_url_and_branch(addon["url"], addon["branch"])
|
||||
|
||||
@@ -236,8 +236,8 @@ class CreateAddonListWorker(QtCore.QThread):
|
||||
repo = Addon(name, url, state, branch)
|
||||
md_file = os.path.join(addondir, "package.xml")
|
||||
if os.path.isfile(md_file):
|
||||
repo.load_metadata_file(md_file)
|
||||
repo.installed_version = repo.metadata.version
|
||||
repo.installed_metadata = MetadataReader.from_file(md_file)
|
||||
repo.installed_version = repo.installed_metadata.version
|
||||
repo.updated_timestamp = os.path.getmtime(md_file)
|
||||
repo.verify_url_and_branch(url, branch)
|
||||
|
||||
@@ -453,8 +453,6 @@ class LoadPackagesFromCacheWorker(QtCore.QThread):
|
||||
if os.path.isfile(repo_metadata_cache_path):
|
||||
try:
|
||||
repo.load_metadata_file(repo_metadata_cache_path)
|
||||
repo.installed_version = repo.metadata.version
|
||||
repo.updated_timestamp = os.path.getmtime(repo_metadata_cache_path)
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintLog(f"Failed loading {repo_metadata_cache_path}\n")
|
||||
FreeCAD.Console.PrintLog(str(e) + "\n")
|
||||
@@ -608,15 +606,36 @@ class UpdateChecker:
|
||||
)
|
||||
wb.set_status(Addon.Status.CANNOT_CHECK)
|
||||
|
||||
def _branch_name_changed(self, package: Addon) -> bool:
|
||||
clone_dir = os.path.join(self.moddir, package.name)
|
||||
installed_metadata_file = os.path.join(clone_dir, "package.xml")
|
||||
if not os.path.isfile(installed_metadata_file):
|
||||
return False
|
||||
try:
|
||||
installed_metadata = MetadataReader.from_file(installed_metadata_file)
|
||||
installed_default_branch = get_branch_from_metadata(installed_metadata)
|
||||
remote_default_branch = get_branch_from_metadata(package.metadata)
|
||||
if installed_default_branch != remote_default_branch:
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
return False
|
||||
|
||||
def check_package(self, package: Addon) -> None:
|
||||
"""Given a packaged Addon package, check it for updates. If git is available that is
|
||||
used. If not, the package's metadata is examined, and if the metadata file has changed
|
||||
compared to the installed copy, an update is flagged."""
|
||||
compared to the installed copy, an update is flagged. In addition, a change to the
|
||||
default branch name triggers an update."""
|
||||
|
||||
clonedir = self.moddir + os.sep + package.name
|
||||
if os.path.exists(clonedir):
|
||||
clone_dir = self.moddir + os.sep + package.name
|
||||
if os.path.exists(clone_dir):
|
||||
|
||||
# First, try to just do a git-based update, which will give the most accurate results:
|
||||
# First, see if the branch name changed, which automatically triggers an update
|
||||
if self._branch_name_changed(package):
|
||||
package.set_status(Addon.Status.UPDATE_AVAILABLE)
|
||||
return
|
||||
|
||||
# Next, try to just do a git-based update, which will give the most accurate results:
|
||||
if self.git_manager:
|
||||
self.check_workbench(package)
|
||||
if package.status() != Addon.Status.CANNOT_CHECK:
|
||||
@@ -624,7 +643,7 @@ class UpdateChecker:
|
||||
return
|
||||
|
||||
# If we were unable to do a git-based update, try using the package.xml file instead:
|
||||
installed_metadata_file = os.path.join(clonedir, "package.xml")
|
||||
installed_metadata_file = os.path.join(clone_dir, "package.xml")
|
||||
if not os.path.isfile(installed_metadata_file):
|
||||
# If there is no package.xml file, then it's because the package author added it
|
||||
# after the last time the local installation was updated. By definition, then,
|
||||
@@ -852,6 +871,8 @@ class CacheMacroCodeWorker(QtCore.QThread):
|
||||
)
|
||||
with self.lock:
|
||||
self.failed.append(macro_name)
|
||||
self.repo_queue.task_done()
|
||||
self.counter += 1
|
||||
|
||||
|
||||
class GetMacroDetailsWorker(QtCore.QThread):
|
||||
|
||||
@@ -415,7 +415,6 @@ class PythonPackageManager:
|
||||
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
|
||||
known_python_versions_string = pref.GetString("KnownPythonVersions", "[]")
|
||||
known_python_versions = json.loads(known_python_versions_string)
|
||||
print(json.dumps(known_python_versions, indent=4))
|
||||
return known_python_versions
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -31,10 +31,14 @@ from PySide import QtCore, QtGui, QtWidgets
|
||||
import addonmanager_freecad_interface as fci
|
||||
|
||||
import addonmanager_utilities as utils
|
||||
from addonmanager_metadata import Version, UrlType, get_first_supported_freecad_version
|
||||
from addonmanager_metadata import (
|
||||
Version,
|
||||
get_first_supported_freecad_version,
|
||||
get_branch_from_metadata,
|
||||
)
|
||||
from addonmanager_workers_startup import GetMacroDetailsWorker, CheckSingleUpdateWorker
|
||||
from addonmanager_readme_viewer import ReadmeViewer
|
||||
from addonmanager_git import GitManager, NoGitFound, GitFailed
|
||||
from addonmanager_git import GitManager, NoGitFound
|
||||
from Addon import Addon
|
||||
from change_branch import ChangeBranchDialog
|
||||
|
||||
@@ -150,16 +154,30 @@ class PackageDetails(QtWidgets.QWidget):
|
||||
|
||||
if status == Addon.Status.UPDATE_AVAILABLE:
|
||||
if repo.metadata:
|
||||
installed_version_string += (
|
||||
"<b>"
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"On branch {}, update available to version",
|
||||
).format(repo.branch)
|
||||
+ " "
|
||||
)
|
||||
installed_version_string += str(repo.metadata.version)
|
||||
installed_version_string += ".</b>"
|
||||
name_change = False
|
||||
if repo.installed_metadata:
|
||||
old_branch = get_branch_from_metadata(repo.installed_metadata)
|
||||
new_branch = get_branch_from_metadata(repo.metadata)
|
||||
if old_branch != new_branch:
|
||||
installed_version_string += (
|
||||
"<b>"
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"Currently on branch {}, name changed to {}",
|
||||
).format(old_branch, new_branch)
|
||||
) + ".</b> "
|
||||
name_change = True
|
||||
if not name_change:
|
||||
installed_version_string += (
|
||||
"<b>"
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"On branch {}, update available to version",
|
||||
).format(repo.branch)
|
||||
+ " "
|
||||
)
|
||||
installed_version_string += str(repo.metadata.version)
|
||||
installed_version_string += ".</b>"
|
||||
elif repo.macro and repo.macro.version:
|
||||
installed_version_string += (
|
||||
"<b>" + translate("AddonsInstaller", "Update available to version") + " "
|
||||
@@ -364,7 +382,6 @@ class PackageDetails(QtWidgets.QWidget):
|
||||
|
||||
# If all four above checks passed, then it's possible for us to switch
|
||||
# branches, if there are any besides the one we are on: show the button
|
||||
print("Showing the button")
|
||||
self.ui.buttonChangeBranch.show()
|
||||
|
||||
def set_disable_button_state(self):
|
||||
|
||||
@@ -454,11 +454,14 @@ class PackageListItemDelegate(QtWidgets.QStyledItemDelegate):
|
||||
|
||||
installed_version_string = ""
|
||||
if repo.status() != Addon.Status.NOT_INSTALLED:
|
||||
if repo.installed_version:
|
||||
if repo.installed_version or repo.installed_metadata:
|
||||
installed_version_string = (
|
||||
"<br/>" + translate("AddonsInstaller", "Installed version") + ": "
|
||||
)
|
||||
installed_version_string += str(repo.installed_version)
|
||||
if repo.installed_metadata:
|
||||
installed_version_string += str(repo.installed_metadata.version)
|
||||
elif repo.installed_version:
|
||||
installed_version_string += str(repo.installed_version)
|
||||
else:
|
||||
installed_version_string = "<br/>" + translate("AddonsInstaller", "Unknown version")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user