From 4c3b8283d1b97e5986727c996446e2a465f44654 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra <4995967+baszalmstra@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:54:09 +0800 Subject: [PATCH] rename packages --- vinca/distro.py | 8 +++ vinca/generate_gha.py | 4 +- vinca/main.py | 52 ++++++++------- vinca/resolve.py | 3 +- vinca/template.py | 10 ++- vinca/templates/bld_ament_python.bat.in | 2 +- vinca/templates/bld_catkin.bat.in | 8 +-- vinca/templates/bld_catkin_merge.bat.in | 2 +- vinca/templates/build_ament_python.sh.in | 4 +- vinca/templates/build_catkin.sh.in | 10 +-- vinca/test_naming_scheme.py | 83 ++++++++++++++++++++++++ vinca/utils.py | 11 ++-- 12 files changed, 149 insertions(+), 48 deletions(-) create mode 100644 vinca/test_naming_scheme.py diff --git a/vinca/distro.py b/vinca/distro.py index 83e25d6..327baa5 100644 --- a/vinca/distro.py +++ b/vinca/distro.py @@ -171,6 +171,14 @@ def get_release_package_xml(self, pkg_name): def check_ros1(self): return self._distribution_type == "ros1" + def get_ros_version(self): + """Get ROS version number (1 or 2)""" + return "1" if self.check_ros1() else "2" + + def get_package_prefix(self): + """Get the package name prefix (ros for ROS1, ros2 for ROS2)""" + return "ros" if self.check_ros1() else "ros2" + def get_python_version(self): return self._python_version diff --git a/vinca/generate_gha.py b/vinca/generate_gha.py index 86f2e45..95025da 100644 --- a/vinca/generate_gha.py +++ b/vinca/generate_gha.py @@ -480,8 +480,8 @@ def main(): ] if platform == "emscripten-wasm32": # Hot fix to add the only ros package inside a if else statement - if "ros-humble-rmw-wasm-cpp" in str(reqs): - requirements[pkg_name].append("ros-humble-rmw-wasm-cpp") + if "ros2-rmw-wasm-cpp" in str(reqs): + requirements[pkg_name].append("ros2-rmw-wasm-cpp") G = nx.DiGraph() for pkg, reqs in requirements.items(): diff --git a/vinca/main.py b/vinca/main.py index 65066fc..9d8b78e 100644 --- a/vinca/main.py +++ b/vinca/main.py @@ -425,10 +425,14 @@ def generate_output(pkg_shortname, vinca_conf, distro, version, all_pkgs=None): "ros_environment", ]: output["requirements"]["host"].append( - f"ros-{config.ros_distro}-ros-environment" + f"{distro.get_package_prefix()}-ros-environment" + ) + output["requirements"]["host"].append( + f"{distro.get_package_prefix()}-ros-workspace" + ) + output["requirements"]["run"].append( + f"{distro.get_package_prefix()}-ros-workspace" ) - output["requirements"]["host"].append(f"ros-{config.ros_distro}-ros-workspace") - output["requirements"]["run"].append(f"ros-{config.ros_distro}-ros-workspace") rm_deps, add_deps = get_depmods(vinca_conf, pkg.name) gdeps = [] @@ -469,7 +473,7 @@ def generate_output(pkg_shortname, vinca_conf, distro, version, all_pkgs=None): output["requirements"]["build"].append( { "if": "build_platform != target_platform", - "then": [f"ros-{config.ros_distro}-cyclonedds"], + "then": [f"{distro.get_package_prefix()}-cyclonedds"], } ) @@ -519,32 +523,31 @@ def sortkey(k): if "cmake" not in output["requirements"]["build"]: output["requirements"]["build"].append("cmake") - if f"ros-{config.ros_distro}-mimick-vendor" in output["requirements"]["build"]: - output["requirements"]["build"].remove(f"ros-{config.ros_distro}-mimick-vendor") + mimick_vendor_name = f"{distro.get_package_prefix()}-mimick-vendor" + if mimick_vendor_name in output["requirements"]["build"]: + output["requirements"]["build"].remove(mimick_vendor_name) output["requirements"]["build"].append( { "if": "target_platform != 'emscripten-wasm32'", - "then": [f"ros-{config.ros_distro}-mimick-vendor"], + "then": [mimick_vendor_name], } ) - if f"ros-{config.ros_distro}-mimick-vendor" in output["requirements"]["host"]: - output["requirements"]["host"].remove(f"ros-{config.ros_distro}-mimick-vendor") + if mimick_vendor_name in output["requirements"]["host"]: + output["requirements"]["host"].remove(mimick_vendor_name) output["requirements"]["build"].append( { "if": "target_platform != 'emscripten-wasm32'", - "then": [f"ros-{config.ros_distro}-mimick-vendor"], + "then": [mimick_vendor_name], } ) - if ( - f"ros-{config.ros_distro}-rosidl-default-generators" - in output["requirements"]["host"] - ): + rosidl_generators_name = f"{distro.get_package_prefix()}-rosidl-default-generators" + if rosidl_generators_name in output["requirements"]["host"]: output["requirements"]["build"].append( { "if": "target_platform == 'emscripten-wasm32'", - "then": [f"ros-{config.ros_distro}-rosidl-default-generators"], + "then": [rosidl_generators_name], } ) @@ -558,7 +561,8 @@ def sortkey(k): } ] - if f"ros-{config.ros_distro}-pybind11-vendor" in output["requirements"]["host"]: + pybind11_vendor_name = f"{distro.get_package_prefix()}-pybind11-vendor" + if pybind11_vendor_name in output["requirements"]["host"]: output["requirements"]["host"] += ["pybind11"] if "pybind11" in output["requirements"]["host"]: output["requirements"]["build"] += [ @@ -983,7 +987,7 @@ def generate_mutex_package_recipe(vinca_conf, distro): def parse_package(pkg, distro, vinca_conf, path): name = pkg["name"].replace("_", "-") - final_name = f"ros-{distro.name}-{name}" + final_name = f"{distro.get_package_prefix()}-{name}" recipe = { "package": {"name": final_name, "version": pkg["version"]}, @@ -1148,7 +1152,7 @@ def main(): for o in outputs: sources[o["package"]["name"]] = o["source"] del o["source"] - write_recipe(sources, outputs, vinca_conf) + write_recipe(sources, outputs, vinca_conf, distro) else: if arguments.skip_already_built_repodata or vinca_conf.get("skip_existing"): @@ -1168,10 +1172,10 @@ def main(): additional_recipe_names.add(add_rec_y["package"]["name"]) else: if add_rec_y["package"]["name"] not in [ - "ros-humble-rmw-wasm-cpp", - "ros-humble-wasm-cpp", - "ros-humble-dynmsg", - "ros-humble-test-wasm", + "ros2-rmw-wasm-cpp", + "ros2-wasm-cpp", + "ros2-dynmsg", + "ros2-test-wasm", ]: additional_recipe_names.add(add_rec_y["package"]["name"]) @@ -1235,9 +1239,9 @@ def main(): outputs = generate_outputs(distro, vinca_conf) if arguments.multiple_file: - write_recipe(source, outputs, vinca_conf, False) + write_recipe(source, outputs, vinca_conf, distro, False) else: - write_recipe(source, outputs, vinca_conf) + write_recipe(source, outputs, vinca_conf, distro) if unsatisfied_deps: print("Unsatisfied dependencies:", unsatisfied_deps) diff --git a/vinca/resolve.py b/vinca/resolve.py index 883b2ba..c883f8a 100644 --- a/vinca/resolve.py +++ b/vinca/resolve.py @@ -69,8 +69,7 @@ def resolve_pkgname(pkg_shortname, vinca_conf, distro, is_rundep=False): return [] else: return [ - "ros-%s-%s" - % (vinca_conf["ros_distro"], pkg_shortname.replace("_", "-")) + "%s-%s" % (distro.get_package_prefix(), pkg_shortname.replace("_", "-")) ] else: if is_rundep: # for run dependencies, remove the version diff --git a/vinca/template.py b/vinca/template.py index fa30d47..b362c94 100644 --- a/vinca/template.py +++ b/vinca/template.py @@ -77,7 +77,7 @@ def copyfile_with_exec_permissions(source_file, destination_file): ) -def write_recipe(source, outputs, vinca_conf, single_file=True): +def write_recipe(source, outputs, vinca_conf, distro, single_file=True): # single_file = False if single_file: file = yaml.YAML() @@ -200,6 +200,7 @@ def write_recipe(source, outputs, vinca_conf, single_file=True): generate_build_script_for_recipe( script_filename, recipe_dir / script_filename, + distro.get_package_prefix(), additional_cmake_args, additional_folder, ) @@ -238,7 +239,11 @@ def generate_template(template_in, template_out, extra_globals=None): def generate_build_script_for_recipe( - script_name, output_path, additional_cmake_args="", additional_folder="" + script_name, + output_path, + ros_package_prefix, + additional_cmake_args="", + additional_folder="", ): """Generate a specific build script directly in the recipe directory.""" import pkg_resources @@ -261,6 +266,7 @@ def generate_build_script_for_recipe( ) with open(output_path, "w") as output_file: extra_globals = {} + extra_globals["ros_package_prefix"] = ros_package_prefix if additional_cmake_args: extra_globals["additional_cmake_args"] = additional_cmake_args else: diff --git a/vinca/templates/bld_ament_python.bat.in b/vinca/templates/bld_ament_python.bat.in index 8d6ff92..5640724 100644 --- a/vinca/templates/bld_ament_python.bat.in +++ b/vinca/templates/bld_ament_python.bat.in @@ -5,7 +5,7 @@ setlocal set "PYTHONPATH=%LIBRARY_PREFIX%\lib\site-packages;%SP_DIR%" pushd %SRC_DIR%\%PKG_NAME%\src\work\@(additional_folder) -set "PKG_NAME_SHORT=%PKG_NAME:*ros-@(ros_distro)-=%" +set "PKG_NAME_SHORT=%PKG_NAME:*@(ros_package_prefix)-=%" set "PKG_NAME_SHORT=%PKG_NAME_SHORT:-=_%" :: If there is a setup.cfg that contains install-scripts then use pip to install diff --git a/vinca/templates/bld_catkin.bat.in b/vinca/templates/bld_catkin.bat.in index dc40f72..f534ce3 100644 --- a/vinca/templates/bld_catkin.bat.in +++ b/vinca/templates/bld_catkin.bat.in @@ -15,7 +15,7 @@ set CXX=cl.exe set CL=/DROS_BUILD_SHARED_LIBS=1 /DNOGDI=1 set "CATKIN_BUILD_BINARY_PACKAGE_ARGS=-DCATKIN_BUILD_BINARY_PACKAGE=1" -if "%PKG_NAME%" == "ros-@(ros_distro)-catkin" ( +if "%PKG_NAME%" == "@(ros_package_prefix)-catkin" ( :: create catkin cookie to make it is a catkin workspace type NUL > %LIBRARY_PREFIX%\.catkin :: keep the workspace activation scripts (e.g., local_setup.bat) @@ -46,7 +46,7 @@ cmake ^ %SRC_DIR%\%PKG_NAME%\src\work\@(additional_folder) if errorlevel 1 exit 1 -if "%PKG_NAME%" == "ros-@(ros_distro)-eigenpy" ( +if "%PKG_NAME%" == "@(ros_package_prefix)-eigenpy" ( cmake --build . --config Release --target all --parallel 1 if errorlevel 1 exit 1 ) else ( @@ -62,7 +62,7 @@ if "%SKIP_TESTING%" == "OFF" ( cmake --build . --config Release --target install if errorlevel 1 exit 1 -if "%PKG_NAME%" == "ros-@(ros_distro)-catkin" ( +if "%PKG_NAME%" == "@(ros_package_prefix)-catkin" ( :: Copy the [de]activate scripts to %PREFIX%\etc\conda\[de]activate.d. :: This will allow them to be run on environment activation. for %%F in (activate deactivate) DO ( @@ -71,7 +71,7 @@ if "%PKG_NAME%" == "ros-@(ros_distro)-catkin" ( ) ) -if "%PKG_NAME%" == "ros-@(ros_distro)-ros-workspace" ( +if "%PKG_NAME%" == "@(ros_package_prefix)-ros-workspace" ( :: Copy the [de]activate scripts to %PREFIX%\etc\conda\[de]activate.d. :: This will allow them to be run on environment activation. for %%F in (activate deactivate) DO ( diff --git a/vinca/templates/bld_catkin_merge.bat.in b/vinca/templates/bld_catkin_merge.bat.in index 7ff5a7a..24512c2 100644 --- a/vinca/templates/bld_catkin_merge.bat.in +++ b/vinca/templates/bld_catkin_merge.bat.in @@ -13,7 +13,7 @@ set CXX=cl.exe :: https://learn.microsoft.com/en-us/cpp/build/reference/cl-environment-variables?view=msvc-170 set CL=/DROS_BUILD_SHARED_LIBS=1 /DNOGDI=1 -set CATKIN_MAKE_ISOLATED=src\ros-@(ros_distro)-catkin\bin\catkin_make_isolated +set CATKIN_MAKE_ISOLATED=src\@(ros_package_prefix)-catkin\bin\catkin_make_isolated set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH:\=/% %PYTHON% %CATKIN_MAKE_ISOLATED% ^ diff --git a/vinca/templates/build_ament_python.sh.in b/vinca/templates/build_ament_python.sh.in index 5151721..5cbffb0 100644 --- a/vinca/templates/build_ament_python.sh.in +++ b/vinca/templates/build_ament_python.sh.in @@ -7,8 +7,8 @@ pushd $SRC_DIR/$PKG_NAME/src/work/@(additional_folder) # If there is a setup.cfg that contains install-scripts then we should not set it here if [ -f setup.cfg ] && grep -q "install[-_]scripts" setup.cfg; then - # Remove e.g. ros-humble- from PKG_NAME - PKG_NAME_SHORT=${PKG_NAME#*ros-@(ros_distro)-} + # Remove e.g. ros2- or ros- from PKG_NAME + PKG_NAME_SHORT=${PKG_NAME#*@(ros_package_prefix)-} # Substitute "-" with "_" PKG_NAME_SHORT=${PKG_NAME_SHORT//-/_} INSTALL_SCRIPTS_ARG="--install-scripts=$PREFIX/lib/$PKG_NAME_SHORT" diff --git a/vinca/templates/build_catkin.sh.in b/vinca/templates/build_catkin.sh.in index 94729fb..f7dee2b 100644 --- a/vinca/templates/build_catkin.sh.in +++ b/vinca/templates/build_catkin.sh.in @@ -5,7 +5,7 @@ set -eo pipefail CATKIN_BUILD_BINARY_PACKAGE="ON" -if [ "${PKG_NAME}" == "ros-@(ros_distro)-catkin" ]; then +if [ "${PKG_NAME}" == "@(ros_package_prefix)-catkin" ]; then # create catkin cookie to make it is a catkin workspace touch $PREFIX/.catkin # keep the workspace activation scripts (e.g., local_setup.bat) @@ -85,7 +85,7 @@ fi export SKIP_TESTING=@(skip_testing) -if [ "${PKG_NAME}" == "ros-noetic-euslisp" ] || [ "${PKG_NAME}" = "ros-noetic-jskeus" ] || [ "${PKG_NAME}" = "ros-noetic-roseus" ]; then +if [ "${PKG_NAME}" == "ros-euslisp" ] || [ "${PKG_NAME}" = "ros-jskeus" ] || [ "${PKG_NAME}" = "ros-roseus" ]; then GENERATOR="Unix Makefiles" else GENERATOR="Ninja" @@ -123,7 +123,7 @@ fi cmake --build . --config Release --target install -if [ "${PKG_NAME}" == "ros-@(ros_distro)-catkin" ]; then +if [ "${PKG_NAME}" == "@(ros_package_prefix)-catkin" ]; then # Copy the [de]activate scripts to $PREFIX/etc/conda/[de]activate.d. # This will allow them to be run on environment activation. for CHANGE in "activate" "deactivate" @@ -133,7 +133,7 @@ if [ "${PKG_NAME}" == "ros-@(ros_distro)-catkin" ]; then done fi -if [ "${PKG_NAME}" == "ros-@(ros_distro)-environment" ]; then +if [ "${PKG_NAME}" == "@(ros_package_prefix)-environment" ]; then for SCRIPT in "1.ros_distro.sh" "1.ros_etc_dir.sh" "1.ros_package_path.sh" "1.ros_python_version.sh" "1.ros_version.sh" do mkdir -p "${PREFIX}/etc/conda/activate.d" @@ -141,7 +141,7 @@ if [ "${PKG_NAME}" == "ros-@(ros_distro)-environment" ]; then done fi -if [ "${PKG_NAME}" == "ros-@(ros_distro)-ros-workspace" ]; then +if [ "${PKG_NAME}" == "@(ros_package_prefix)-ros-workspace" ]; then # Copy the [de]activate scripts to $PREFIX/etc/conda/[de]activate.d. # This will allow them to be run on environment activation. for CHANGE in "activate" "deactivate" diff --git a/vinca/test_naming_scheme.py b/vinca/test_naming_scheme.py new file mode 100644 index 0000000..2fa97d9 --- /dev/null +++ b/vinca/test_naming_scheme.py @@ -0,0 +1,83 @@ +"""Tests for the ROS package naming scheme.""" + +import pytest +from unittest.mock import Mock +from vinca.utils import ensure_name_is_without_distro_prefix_and_with_underscores +from vinca.distro import Distro + + +@pytest.mark.parametrize( + "input_name,expected_output", + [ + # ROS2 packages + ("ros2-my-package", "my_package"), + ("ros2-complex-package-name", "complex_package_name"), + ("ros2-ros-environment", "ros_environment"), + ("ros2-ros-workspace", "ros_workspace"), + ("ros2-catkin", "catkin"), + ("ros2-navigation2", "navigation2"), + ("ros2-my-very-long-package-name", "my_very_long_package_name"), + ("ros2-navigation-stack-extra", "navigation_stack_extra"), + ("ros2-my_package_name", "my_package_name"), + # ROS1 packages + ("ros-my-package", "my_package"), + ("ros-test-package", "test_package"), + ("ros-ros-environment", "ros_environment"), + ("ros-ros-workspace", "ros_workspace"), + ("ros-catkin", "catkin"), + ("ros-moveit", "moveit"), + ("ros-simple", "simple"), + # Packages without prefix + ("my-package", "my_package"), + # Edge cases + ("ros2-a", "a"), + ("ros-a", "a"), + ("ros2-ros", "ros"), + ], +) +def test_package_normalization(input_name, expected_output): + """Test package name normalization for various inputs.""" + vinca_conf = {} + result = ensure_name_is_without_distro_prefix_and_with_underscores( + input_name, vinca_conf + ) + assert result == expected_output + + +@pytest.mark.parametrize( + "package_name", + [ + "ros2-my-package", + "ros2-complex-package-name", + "ros-simple-package", + "ros-another-test", + ], +) +def test_no_hyphens_in_output(package_name): + """Test that normalized names contain no hyphens.""" + vinca_conf = {} + result = ensure_name_is_without_distro_prefix_and_with_underscores( + package_name, vinca_conf + ) + assert "-" not in result + + +@pytest.mark.parametrize( + "distribution_type,expected_prefix,expected_version", + [ + ("ros1", "ros", "1"), + ("ros2", "ros2", "2"), + ], +) +def test_distro_prefix_and_version( + distribution_type, expected_prefix, expected_version +): + """Test that Distro returns correct package prefix and ROS version.""" + distro = Mock(spec=Distro) + distro._distribution_type = distribution_type + distro.check_ros1 = lambda: distro._distribution_type == "ros1" + distro.get_package_prefix = lambda: "ros" if distro.check_ros1() else "ros2" + distro.get_ros_version = lambda: "1" if distro.check_ros1() else "2" + + assert distro.get_package_prefix() == expected_prefix + assert distro.get_ros_version() == expected_version diff --git a/vinca/utils.py b/vinca/utils.py index e5e2d11..1589f0d 100644 --- a/vinca/utils.py +++ b/vinca/utils.py @@ -69,13 +69,14 @@ def get_repodata(url_or_path, platform=None): def ensure_name_is_without_distro_prefix_and_with_underscores(name, vinca_conf): """ - Ensure that the name is without distro prefix and with underscores - e.g. "ros-humble-pkg-name" -> "pkg_name" + Ensure that the name is without ROS prefix and with underscores + e.g. "ros2-pkg-name" -> "pkg_name" or "ros-pkg-name" -> "pkg_name" """ newname = name.replace("-", "_") - distro_prefix = "ros_" + vinca_conf.get("ros_distro") + "_" - if newname.startswith(distro_prefix): - newname = newname.replace(distro_prefix, "") + if newname.startswith("ros2_"): + newname = newname[5:] # Remove "ros2_" + elif newname.startswith("ros_"): + newname = newname[4:] # Remove "ros_" return newname