Skip to content

Commit 4e9edcd

Browse files
committed
Addon Manager: improve git branch changing
1 parent fbb1225 commit 4e9edcd

File tree

4 files changed

+83
-22
lines changed

4 files changed

+83
-22
lines changed

src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py

Whitespace-only changes.

src/Mod/AddonManager/addonmanager_freecad_interface.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949

5050
if FreeCAD.GuiUp:
5151
import FreeCADGui
52-
else:
53-
FreeCADGui = None
52+
53+
loadUi = FreeCADGui.PySideUic.loadUi
5454

5555
except ImportError:
5656
FreeCAD = None
@@ -63,7 +63,7 @@ def translate(_context: str, string: str, _desc: str = "") -> str:
6363
return string
6464

6565
def Version():
66-
return 0, 22, 0, "dev"
66+
return 1, 1, 0, "dev"
6767

6868
class ConsoleReplacement:
6969
"""If FreeCAD's Console is not available, create a replacement by redirecting FreeCAD

src/Mod/AddonManager/addonmanager_utilities.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ def get_python_exe():
6969
import urllib.request
7070
import ssl
7171

72+
if fci.FreeCADGui:
73+
loadUi = fci.loadUi
74+
else:
75+
try:
76+
from PySide6.QtUiTools import QUiLoader
77+
except ImportError:
78+
from PySide2.QtUiTools import QUiLoader
79+
80+
def loadUi(ui_file: str) -> QtWidgets.QWidget:
81+
q_ui_file = QtCore.QFile(ui_file)
82+
q_ui_file.open(QtCore.QFile.OpenModeFlag.ReadOnly)
83+
loader = QUiLoader()
84+
return loader.load(ui_file)
85+
86+
7287
# @package AddonManager_utilities
7388
# \ingroup ADDONMANAGER
7489
# \brief Utilities to work across different platforms, providers and python versions

src/Mod/AddonManager/change_branch.py

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: LGPL-2.1-or-later
22
# ***************************************************************************
33
# * *
4-
# * Copyright (c) 2022-2023 FreeCAD Project Association *
4+
# * Copyright (c) 2022-2025 The FreeCAD Project Association AISBL *
55
# * *
66
# * This file is part of FreeCAD. *
77
# * *
@@ -22,14 +22,22 @@
2222
# ***************************************************************************
2323

2424
import os
25+
from typing import Dict
2526

26-
import FreeCAD
27-
import FreeCADGui
28-
from addonmanager_git import initialize_git
27+
import addonmanager_freecad_interface as fci
28+
import addonmanager_utilities as utils
2929

30-
from PySide import QtWidgets, QtCore
30+
from addonmanager_git import initialize_git, GitFailed
3131

32-
translate = FreeCAD.Qt.translate
32+
try:
33+
from PySide import QtWidgets, QtCore
34+
except ImportError:
35+
try:
36+
from PySide6 import QtWidgets, QtCore
37+
except ImportError:
38+
from PySide2 import QtWidgets, QtCore
39+
40+
translate = fci.translate
3341

3442

3543
class ChangeBranchDialog(QtWidgets.QWidget):
@@ -39,9 +47,7 @@ class ChangeBranchDialog(QtWidgets.QWidget):
3947
def __init__(self, path: str, parent=None):
4048
super().__init__(parent)
4149

42-
self.ui = FreeCADGui.PySideUic.loadUi(
43-
os.path.join(os.path.dirname(__file__), "change_branch.ui")
44-
)
50+
self.ui = utils.loadUi(os.path.join(os.path.dirname(__file__), "change_branch.ui"))
4551

4652
self.item_filter = ChangeBranchDialogFilter()
4753
self.ui.tableView.setModel(self.item_filter)
@@ -54,6 +60,9 @@ def __init__(self, path: str, parent=None):
5460

5561
# Figure out what row gets selected:
5662
git_manager = initialize_git()
63+
if git_manager is None:
64+
return
65+
5766
row = 0
5867
self.current_ref = git_manager.current_branch(path)
5968
selection_model = self.ui.tableView.selectionModel()
@@ -111,14 +120,51 @@ def exec(self):
111120
if result == QtWidgets.QMessageBox.Cancel:
112121
return
113122

114-
gm = initialize_git()
115-
remote_name = ref["ref_name"]
116-
_, _, local_name = ref["ref_name"].rpartition("/")
123+
self._change_branch(self.item_model.path, ref)
124+
125+
def _change_branch(self, path: str, ref: Dict[str, str]) -> None:
126+
"""Change the git clone in `path` to git ref `ref`. Emits the branch_changed signal
127+
on success."""
128+
remote_name = ref["ref_name"]
129+
_, _, local_name = ref["ref_name"].rpartition("/")
130+
gm = initialize_git()
131+
if gm is None:
132+
self._show_no_git_dialog()
133+
return
134+
135+
try:
117136
if ref["upstream"]:
118-
gm.checkout(self.item_model.path, remote_name)
137+
gm.checkout(path, remote_name)
119138
else:
120-
gm.checkout(self.item_model.path, remote_name, args=["-b", local_name])
139+
gm.checkout(path, remote_name, args=["-b", local_name])
121140
self.branch_changed.emit(self.current_ref, local_name)
141+
except GitFailed:
142+
self._show_git_failed_dialog()
143+
144+
def _show_no_git_dialog(self):
145+
QtWidgets.QMessageBox.critical(
146+
self,
147+
translate("AddonsInstaller", "Cannot find git"),
148+
translate(
149+
"AddonsInstaller",
150+
"Could not find git executable: cannot change branch",
151+
),
152+
QtWidgets.QMessageBox.Ok,
153+
QtWidgets.QMessageBox.Ok,
154+
)
155+
156+
def _show_git_failed_dialog(self):
157+
QtWidgets.QMessageBox.critical(
158+
self,
159+
translate("AddonsInstaller", "git operation failed"),
160+
translate(
161+
"AddonsInstaller",
162+
"Git returned an error code when attempting to change branch. There may be "
163+
"more details in the Report View.",
164+
),
165+
QtWidgets.QMessageBox.Ok,
166+
QtWidgets.QMessageBox.Ok,
167+
)
122168

123169

124170
class ChangeBranchDialogModel(QtCore.QAbstractTableModel):
@@ -235,11 +281,11 @@ def _remove_tracking_duplicates(self):
235281

236282
class ChangeBranchDialogFilter(QtCore.QSortFilterProxyModel):
237283
def lessThan(self, left: QtCore.QModelIndex, right: QtCore.QModelIndex):
238-
leftData = self.sourceModel().data(left, ChangeBranchDialogModel.DataSortRole)
239-
rightData = self.sourceModel().data(right, ChangeBranchDialogModel.DataSortRole)
240-
if leftData is None or rightData is None:
241-
if rightData is not None:
284+
left_data = self.sourceModel().data(left, ChangeBranchDialogModel.DataSortRole)
285+
right_data = self.sourceModel().data(right, ChangeBranchDialogModel.DataSortRole)
286+
if left_data is None or right_data is None:
287+
if right_data is not None:
242288
return True
243289
else:
244290
return False
245-
return leftData < rightData
291+
return left_data < right_data

0 commit comments

Comments
 (0)