mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Bonsai offers to install Git and ifcmerge
If Git isn't installed on Windows, the Git panel now offers to install it from the Microsoft Store using `winget`. Then if ifcmerge isn't installed on Linux or Windows, the Git panel offers to install it from copies bundled in the Bonsai ZIP package. Note that ifcmerge.exe increases the size of the Bonsai ZIP download by about 7MB.
This commit is contained in:
@@ -229,6 +229,14 @@ endif
|
||||
# Required for Desktop icon and file association
|
||||
cp -r bonsai/libs/desktop build/bonsai/libs/
|
||||
|
||||
# required for three-way git merging
|
||||
ifeq ($(PLATFORM), win)
|
||||
cd build/bonsai/libs/desktop && wget https://github.com/brunopostle/ifcmerge/releases/download/2024-06-24/ifcmerge.zip
|
||||
cd build/bonsai/libs/desktop && unzip ifcmerge.zip && rm ifcmerge.zip
|
||||
else
|
||||
cd build/bonsai/libs/desktop && wget https://raw.githubusercontent.com/brunopostle/ifcmerge/main/ifcmerge
|
||||
endif
|
||||
|
||||
# Generate translations module for Bonsai build
|
||||
git clone https://github.com/IfcOpenShell/bonsai-translations.git build/working
|
||||
$(PYTHON) scripts/bonsai_translations.py -i "build/working" -o "build/bonsai"
|
||||
|
||||
@@ -37,6 +37,8 @@ classes = (
|
||||
operator.Push,
|
||||
operator.RefreshGit,
|
||||
operator.SwitchRevision,
|
||||
operator.InstallGit,
|
||||
operator.InstallIfcmerge,
|
||||
prop.IfcGitTag,
|
||||
prop.IfcGitListItem,
|
||||
prop.IfcGitProperties,
|
||||
|
||||
@@ -386,3 +386,36 @@ class ObjectLog(bpy.types.Operator):
|
||||
step_id = context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
core.entity_log(tool.IfcGit, tool.Ifc, step_id, self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class InstallGit(bpy.types.Operator):
|
||||
"""Installs Git if possible"""
|
||||
|
||||
bl_label = "Install Git"
|
||||
bl_idname = "ifcgit.install_git"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
IfcGitData.make_sure_is_loaded()
|
||||
if IfcGitData.data["git_exe"]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
core.install_git(tool.IfcGit, self)
|
||||
refresh()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class InstallIfcmerge(bpy.types.Operator):
|
||||
"""Installs ifcmerge if possible"""
|
||||
|
||||
bl_label = "Install ifcmerge"
|
||||
bl_idname = "ifcgit.install_ifcmerge"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def execute(self, context):
|
||||
core.install_ifcmerge(tool.IfcGit, self)
|
||||
refresh()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import bpy
|
||||
import time
|
||||
import os
|
||||
import platform
|
||||
|
||||
from bonsai.bim.module.ifcgit.data import IfcGitData
|
||||
|
||||
@@ -26,7 +27,22 @@ class IFCGIT_PT_panel(bpy.types.Panel):
|
||||
if not IfcGitData.data["git_exe"]:
|
||||
row = layout.row()
|
||||
row.label(text="Git is not installed", icon="ERROR")
|
||||
if platform.system() == "Windows":
|
||||
row.operator(
|
||||
"ifcgit.install_git",
|
||||
text="Install Git from Microsoft Store",
|
||||
icon="PACKAGE",
|
||||
)
|
||||
return
|
||||
elif not IfcGitData.data["ifcmerge_exe"]:
|
||||
# TODO check if ifcmerge is up-to-date
|
||||
row = layout.row()
|
||||
row.label(text="ifcmerge is not installed", icon="ERROR")
|
||||
row.operator(
|
||||
"ifcgit.install_ifcmerge",
|
||||
text="Install ifcmerge",
|
||||
icon="PACKAGE",
|
||||
)
|
||||
|
||||
props = context.scene.IfcGitProperties
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import platform
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -130,3 +131,19 @@ def entity_log(ifcgit: tool.IfcGit, ifc: tool.Ifc, step_id: int, operator: bpy.t
|
||||
log_text = ifcgit.entity_log(path_ifc, step_id)
|
||||
# ERROR is only way to display a multi-line message
|
||||
operator.report({"ERROR"}, log_text)
|
||||
|
||||
|
||||
def install_git(ifcgit: tool.IfcGit, operator: bpy.types.Operator) -> None:
|
||||
if platform.system() == "Windows":
|
||||
ifcgit.install_git_windows(operator=operator)
|
||||
else:
|
||||
print("install_git() not implemented")
|
||||
|
||||
|
||||
def install_ifcmerge(ifcgit: tool.IfcGit, operator: bpy.types.Operator) -> None:
|
||||
if platform.system() == "Windows":
|
||||
ifcgit.install_ifcmerge_windows(name_exe="ifcmerge.exe", operator=operator)
|
||||
elif platform.system() == "Linux":
|
||||
ifcgit.install_ifcmerge_linux(name_exe="ifcmerge", operator=operator)
|
||||
elif platform.system() == "Darwin":
|
||||
print("install_ifcmerge() not implemented")
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import shutil
|
||||
import bpy
|
||||
import logging
|
||||
from bonsai.bim import import_ifc
|
||||
@@ -546,6 +548,51 @@ class IfcGit:
|
||||
logtext = "No Git history found :("
|
||||
return logtext
|
||||
|
||||
@classmethod
|
||||
def install_git_windows(cls, operator: bpy.types.Operator) -> None:
|
||||
"""Command to install Git on Windows using winget"""
|
||||
command = ["winget", "install", "--id", "Git.Git", "-e", "--source", "msstore"]
|
||||
try:
|
||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as e:
|
||||
operator.report({"ERROR"}, f"Called Process Error occurred: {e}")
|
||||
except FileNotFoundError:
|
||||
operator.report({"ERROR"}, "Winget is not available. Make sure Windows Package Manager is installed.")
|
||||
|
||||
@classmethod
|
||||
def install_ifcmerge_linux(cls, name_exe: str, operator: bpy.types.Operator) -> None:
|
||||
"""Command to install ifcmerge on Linux"""
|
||||
src_dir = os.path.join(os.path.dirname(__file__), "../libs/desktop")
|
||||
destdir = os.path.join(os.environ["HOME"], ".local", "bin")
|
||||
try:
|
||||
os.makedirs(destdir, exist_ok=True)
|
||||
shutil.copy(os.path.join(src_dir, name_exe), destdir)
|
||||
os.chmod(os.path.join(destdir, name_exe), 0o755)
|
||||
except Exception as e:
|
||||
operator.report({"ERROR"}, f"Error installing file: {e}")
|
||||
|
||||
@classmethod
|
||||
def install_ifcmerge_windows(cls, name_exe: str, operator: bpy.types.Operator) -> None:
|
||||
"""Command to install ifcmerge on Windows"""
|
||||
src_dir = os.path.join(os.path.dirname(__file__), "..\\libs\\desktop")
|
||||
destdir = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Bonsai", "bin")
|
||||
try:
|
||||
os.makedirs(destdir, exist_ok=True)
|
||||
shutil.copy(os.path.join(src_dir, name_exe), destdir)
|
||||
except Exception as e:
|
||||
operator.report({"ERROR"}, f"Error installing file: {e}")
|
||||
|
||||
current_path = os.environ["PATH"]
|
||||
|
||||
if destdir not in current_path:
|
||||
os.environ["PATH"] = current_path + ";" + destdir
|
||||
command = f'setx PATH "%PATH%;{destdir}"'
|
||||
try:
|
||||
subprocess.run(command, check=True, shell=True)
|
||||
print(f"User %PATH% updated permanently with: {destdir}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
operator.report({"ERROR"}, f"Error permanently updating %PATH%: {e}")
|
||||
|
||||
|
||||
class IfcGitRepo:
|
||||
repo: git.Repo = None
|
||||
|
||||
Reference in New Issue
Block a user