Addon Manager: Allow primary branch name change

This commit is contained in:
Chris Hennes
2024-01-30 14:25:08 +01:00
committed by Chris Hennes
parent 430b6c75cb
commit 39043cf176
8 changed files with 117 additions and 31 deletions

View File

@@ -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 ""

View File

@@ -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

View File

@@ -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)

View File

@@ -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"""

View File

@@ -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):

View File

@@ -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

View File

@@ -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):

View File

@@ -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")