diff --git a/.github/workflows/dynamic-ci.yml b/.github/workflows/dynamic-ci.yml
index 8b03e50e5a..8a404bd30c 100644
--- a/.github/workflows/dynamic-ci.yml
+++ b/.github/workflows/dynamic-ci.yml
@@ -60,6 +60,9 @@ jobs:
- "CMakeLists.txt"
- "vcpkg-configuration.json"
- "vcpkg.json"
+ - "Cargo.toml"
+ - "Cargo.lock"
+ - "crates/**"
hooks:
- "git-hooks/**"
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index d58c56092d..f5721d3981 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -77,3 +77,21 @@ jobs:
echo "Run '3rd-party/flutter/bin/dart format' to fix formatting."
exit 1
fi
+
+ - name: Install Rust toolchain
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ components: rustfmt
+
+ - name: Run Rust format check
+ shell: bash
+ run: |
+ if [ -f "Cargo.toml" ]; then
+ if ! cargo fmt --all --check; then
+ echo -n "##[error] Rust code is not properly formatted. "
+ echo "Run 'cargo fmt --all' to fix formatting."
+ exit 1
+ fi
+ else
+ echo "No Cargo.toml found, skipping Rust format check"
+ fi
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index ac2bd5e14e..b76652c0be 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -198,12 +198,13 @@ jobs:
/snap/bin/lxc --project snapcraft exec $instance_name -- bash -c 'cat /proc/sys/kernel/core_pattern'
# Create the directory for the coredumps
/snap/bin/lxc --project snapcraft exec $instance_name -- bash -c 'mkdir -p /coredump'
- # Enable coredumps by setting the core dump size to "unlimited", and run the tests.
+ # Enable coredumps by setting the core dump size to "unlimited", and run the unified test target.
/snap/bin/lxc --project snapcraft exec $instance_name -- bash -c "\
- ulimit -c unlimited && \
+ source /root/.cargo/env && \
+ ulimit -c unlimited && \
env CTEST_OUTPUT_ON_FAILURE=1 \
LD_LIBRARY_PATH=/root/stage/usr/lib/x86_64-linux-gnu/:/root/stage/lib/:/root/parts/multipass/build/lib/ \
- /root/parts/multipass/build/bin/multipass_tests"
+ ctest --test-dir /root/parts/multipass/build --output-on-failure"
- name: Measure coverage
id: measure-coverage
@@ -231,18 +232,38 @@ jobs:
/snap/bin/lxc --project snapcraft exec $instance_name -- \
sh -c "sudo sed -i \"s/use JSON::PP/use JSON::XS/\" \`which geninfo\`"
+ # Install cargo-llvm-cov for Rust coverage
+ /snap/bin/lxc --project snapcraft exec $instance_name -- bash -c "\
+ source /root/.cargo/env && \
+ cargo install cargo-llvm-cov"
+
# Create the directory for the coredumps
/snap/bin/lxc --project snapcraft exec $instance_name -- bash -c 'mkdir -p /coredump'
+
+ # Generate C++ coverage
/snap/bin/lxc --project snapcraft exec $instance_name -- bash -c "\
ulimit -c unlimited && \
env CTEST_OUTPUT_ON_FAILURE=1 \
cmake --build /root/parts/multipass/build --target covreport"
+ # Generate Rust coverage in lcov format
+ /snap/bin/lxc --project snapcraft exec $instance_name -- bash -c "\
+ source /root/.cargo/env && \
+ cargo llvm-cov --manifest-path /root/parts/multipass/src/Cargo.toml \
+ --lcov --output-path /root/parts/multipass/build/rust-coverage.lcov"
+
+ # Merge C++ and Rust coverage reports
+ /snap/bin/lxc --project snapcraft exec $instance_name -- bash -c "\
+ lcov -a /root/parts/multipass/build/coverage.cleaned \
+ -a /root/parts/multipass/build/rust-coverage.lcov \
+ -o /root/parts/multipass/build/combined-coverage.info"
+
- name: Upload coverage
if: ${{ matrix.build-type == 'Coverage' }}
uses: codecov/codecov-action@v5
with:
directory: ${{ steps.coverage-setup.outputs.build }}
+ files: ./combined-coverage.info
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/windows-macos.yml b/.github/workflows/windows-macos.yml
index a004eb8bdc..de60d89cc8 100644
--- a/.github/workflows/windows-macos.yml
+++ b/.github/workflows/windows-macos.yml
@@ -137,7 +137,8 @@ jobs:
pixman \
pkg-config \
python \
- wget
+ wget \
+ rustup-init
- name: Install dependencies from pip
if: ${{ runner.os == 'macOS' }}
@@ -154,7 +155,7 @@ jobs:
if: ${{ runner.os == 'Windows' }}
uses: crazy-max/ghaction-chocolatey@v3
with:
- args: install --yes wget unzip
+ args: install --yes wget unzip rustup.install
- name: Set up vcpkg
id: setup-vcpkg
@@ -255,6 +256,31 @@ jobs:
if: ${{ runner.os == 'Windows' }}
uses: ilammy/msvc-dev-cmd@v1
+ - name: Initialize Rust toolchain
+ shell: bash
+ run: |
+ if [[ "${{ runner.os }}" == "Windows" ]]; then
+ # On Windows, rustup.install from chocolatey should be available
+ if command -v rustup >/dev/null 2>&1; then
+ rustup default stable
+ rustup update
+ else
+ echo "Error: rustup not found. Please ensure it is installed and in the PATH."
+ exit 1
+ fi
+ elif [[ "${{ runner.os }}" == "macOS" ]]; then
+ # On macOS, initialize rustup-init
+ if command -v rustup-init >/dev/null 2>&1; then
+ rustup-init -y --default-toolchain stable
+ source ~/.cargo/env
+ else
+ echo "Error: rustup-init not found. Please ensure it is installed and in the PATH."
+ exit 1
+ fi
+ fi
+ # Add cargo bin to PATH for subsequent steps
+ echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+
- name: Configure
run: >
${{ env.ARCH_WRAPPER }}
@@ -276,9 +302,8 @@ jobs:
run: ccache --show-stats --zero-stats
- name: Test
- working-directory: ${{ env.BUILD_DIR }}
- run: |
- ${{ env.ARCH_WRAPPER }} bin/multipass_tests
+ run: |\
+ ${{ env.ARCH_WRAPPER }} ctest --test-dir ${{ env.BUILD_DIR }} --output-on-failure
- name: Package
id: cmake-package
diff --git a/.gitignore b/.gitignore
index 0152c949dd..3e096b06d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,8 @@ packaging/windows/custom-actions/x64/*
# Python artifacts
*.pyc
+
+
+# Added by cargo
+
+/target
diff --git a/BUILD.linux.md b/BUILD.linux.md
index 500440729f..de44441940 100644
--- a/BUILD.linux.md
+++ b/BUILD.linux.md
@@ -10,6 +10,10 @@ sudo apt install devscripts equivs
mk-build-deps -s sudo -i
```
+### Rust toolchain
+
+Multipass requires Rust for building. Install the Rust toolchain from: https://rustup.rs/
+
## Building
First, go into the repository root and get all the submodules:
diff --git a/BUILD.macOS.md b/BUILD.macOS.md
index f08253091e..1188944683 100644
--- a/BUILD.macOS.md
+++ b/BUILD.macOS.md
@@ -42,6 +42,10 @@ means to obtain these dependencies is with Homebrew .
brew install cmake openssl@3
+### Rust toolchain
+
+Multipass requires Rust for building. Install the Rust toolchain from: https://rustup.rs/
+
Building
---------------------------------------
diff --git a/BUILD.windows.md b/BUILD.windows.md
index dc7d699d6b..312fda9658 100644
--- a/BUILD.windows.md
+++ b/BUILD.windows.md
@@ -19,7 +19,7 @@ choco install cmake ninja qemu openssl git wget unzip -yfd
```
```[pwsh]
-choco install visualstudio2022buildtools visualstudio2022-workload-vctools -yfd
+choco install visualstudio2022buildtools visualstudio2022-workload-vctools rustup.install -yfd
```
NOTE: visualcpp-build-tools is only the installer package. For this reason, choco cannot detect any
@@ -43,6 +43,10 @@ For Windows 11:
1. Go to "Developer Settings"
2. Enable "Developer mode"
+### Rust toolchain
+
+Multipass requires Rust for building. You can install it via Chocolatey (included in the command above) or from: https://rustup.rs/
+
### Qt6
To install Qt6, use `aqt`. First install it with chocolatey:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6ec64092a..73fa0202c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -180,6 +180,29 @@ find_package(gRPC CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
# targets: fmt::fmt, fmt::fmt-header-only
+# Corrosion for Rust + CMake integration
+include(FetchContent)
+
+FetchContent_Declare(
+ Corrosion
+ GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
+ GIT_TAG v0.5 # Use stable version
+)
+FetchContent_MakeAvailable(Corrosion)
+
+# Register Rust build directories for cleaning
+set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES
+ "${CMAKE_BINARY_DIR}/cargo"
+ "${CMAKE_BINARY_DIR}/corrosion"
+)
+
+# Add custom target to also run cargo clean when needed
+add_custom_target(clean-rust
+ COMMAND cargo clean --manifest-path ${CMAKE_SOURCE_DIR}/Cargo.toml
+ COMMENT "Cleaning Cargo workspace artifacts"
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+)
+
# Needs to be here before we set further compilation options
add_subdirectory(3rd-party)
@@ -391,6 +414,20 @@ add_subdirectory(src)
if(MULTIPASS_ENABLE_TESTS)
enable_testing()
add_subdirectory(tests)
+
+ # Add convenience targets for running tests
+ add_custom_target(test-all
+ COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all_tests
+ COMMENT "Running all tests (C++ and Rust) via convenience target"
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+
+ # Add alias for compatibility
+ add_custom_target(check
+ COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all_tests
+ COMMENT "Running all tests (alias for test-all)"
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
endif()
include(packaging/cpack.cmake OPTIONAL)
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000000..a346657c1f
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,427 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "anstyle"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+
+[[package]]
+name = "cc"
+version = "1.2.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+
+[[package]]
+name = "clap"
+version = "4.5.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f"
+dependencies = [
+ "clap_builder",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65"
+dependencies = [
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+[[package]]
+name = "codespan-reporting"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
+dependencies = [
+ "serde",
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "cxx"
+version = "1.0.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7aa144b12f11741f0dab5b4182896afad46faa0598b6a061f7b9d17a21837ba7"
+dependencies = [
+ "cc",
+ "cxxbridge-cmd",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "foldhash",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12d3cbb84fb003242941c231b45ca9417e786e66e94baa39584bd99df3a270b6"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "indexmap",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-cmd"
+version = "1.0.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fa36b7b249d43f67a3f54bd65788e35e7afe64bbc671396387a48b3e8aaea94"
+dependencies = [
+ "clap",
+ "codespan-reporting",
+ "indexmap",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77707c70f6563edc5429618ca34a07241b75ebab35bd01d46697c75d58f8ddfe"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede6c0fb7e318f0a11799b86ee29dcf17b9be2960bd379a6c38e1a96a6010fff"
+dependencies = [
+ "indexmap",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "getrandom"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+
+[[package]]
+name = "indexmap"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.175"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.96"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rustipass"
+version = "0.1.0"
+dependencies = [
+ "cxx",
+ "cxx-build",
+ "rand",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "scratch"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2"
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "unicode-width"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000000..757bc233fb
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,11 @@
+[workspace]
+members = ["crates/rustipass"]
+resolver = "2"
+
+# Root workspace configuration
+[workspace.dependencies]
+cxx = "1.0"
+rand = "0.8"
+
+[workspace.dependencies.cxx-build]
+version = "1.0"
diff --git a/crates/rustipass/Cargo.toml b/crates/rustipass/Cargo.toml
new file mode 100644
index 0000000000..7960a40bab
--- /dev/null
+++ b/crates/rustipass/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "rustipass"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "src/lib.rs"
+crate-type = ["staticlib", "rlib"]
+
+[dependencies]
+cxx = { workspace = true }
+rand = { workspace = true }
+
+[build-dependencies]
+cxx-build = { workspace = true }
diff --git a/crates/rustipass/build.rs b/crates/rustipass/build.rs
new file mode 100644
index 0000000000..d008bfd24a
--- /dev/null
+++ b/crates/rustipass/build.rs
@@ -0,0 +1,5 @@
+fn main() {
+ cxx_build::bridge("src/lib.rs")
+ .flag_if_supported("-std=c++20")
+ .compile("rustipass");
+}
diff --git a/crates/rustipass/src/lib.rs b/crates/rustipass/src/lib.rs
new file mode 100644
index 0000000000..fbdae8e89c
--- /dev/null
+++ b/crates/rustipass/src/lib.rs
@@ -0,0 +1,29 @@
+pub mod petname;
+
+// Re-export petname public API for FFI
+pub use petname::{make_name, new_petname, Petname};
+
+// CXX FFI Bridge for petname module
+#[cxx::bridge(namespace = "multipass::petname")]
+mod petname_ffi {
+ extern "Rust" {
+ type Petname;
+ fn new_petname(num_words: i32, separator: &str) -> Result>;
+ fn make_name(petname: &mut Petname) -> Result;
+ }
+}
+
+// Future modules will have their own FFI bridges:
+// #[cxx::bridge(namespace = "multipass::utils")]
+// mod utils_ffi {
+// extern "Rust" {
+// // utils functions here
+// }
+// }
+
+// #[cxx::bridge(namespace = "multipass::network")]
+// mod network_ffi {
+// extern "Rust" {
+// // network functions here
+// }
+// }
diff --git a/src/petname/adjectives.txt b/crates/rustipass/src/petname/adjectives.txt
similarity index 100%
rename from src/petname/adjectives.txt
rename to crates/rustipass/src/petname/adjectives.txt
diff --git a/src/petname/adverbs.txt b/crates/rustipass/src/petname/adverbs.txt
similarity index 100%
rename from src/petname/adverbs.txt
rename to crates/rustipass/src/petname/adverbs.txt
diff --git a/crates/rustipass/src/petname/mod.rs b/crates/rustipass/src/petname/mod.rs
new file mode 100644
index 0000000000..de83a31835
--- /dev/null
+++ b/crates/rustipass/src/petname/mod.rs
@@ -0,0 +1,95 @@
+use rand::seq::SliceRandom;
+use rand::thread_rng;
+use std::fmt;
+
+const ADJECTIVES: &str = include_str!("adjectives.txt");
+const ADVERBS: &str = include_str!("adverbs.txt");
+const NAMES: &str = include_str!("names.txt");
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum PetnameError {
+ InvalidNumWords(i32),
+ EmptyWordList(String),
+}
+
+impl fmt::Display for PetnameError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ PetnameError::InvalidNumWords(num) => {
+ write!(f, "Invalid number of words: {}. Must be 1, 2, or 3", num)
+ }
+ PetnameError::EmptyWordList(list_name) => {
+ write!(f, "Empty word list: {}", list_name)
+ }
+ }
+ }
+}
+
+impl std::error::Error for PetnameError {}
+
+#[derive(Debug)]
+pub enum NumWords {
+ One,
+ Two,
+ Three,
+}
+
+#[derive(Debug)]
+pub struct Petname {
+ num_words: NumWords,
+ separator: String,
+}
+
+impl Petname {
+ pub fn new(num_words: NumWords, separator: &str) -> Self {
+ Self {
+ num_words,
+ separator: separator.to_string(),
+ }
+ }
+
+ pub fn make_name(&self) -> Result {
+ let mut rng = thread_rng();
+ let adjectives: Vec<&str> = ADJECTIVES.lines().collect();
+ let adverbs: Vec<&str> = ADVERBS.lines().collect();
+ let names: Vec<&str> = NAMES.lines().collect();
+
+ let adjective = adjectives
+ .choose(&mut rng)
+ .ok_or_else(|| PetnameError::EmptyWordList("adjectives".to_string()))?;
+ let adverb = adverbs
+ .choose(&mut rng)
+ .ok_or_else(|| PetnameError::EmptyWordList("adverbs".to_string()))?;
+ let name = names
+ .choose(&mut rng)
+ .ok_or_else(|| PetnameError::EmptyWordList("names".to_string()))?;
+
+ let result = match self.num_words {
+ NumWords::One => name.to_string(),
+ NumWords::Two => format!("{}{}{}", adjective, self.separator, name),
+ NumWords::Three => format!(
+ "{}{}{}{}{}",
+ adverb, self.separator, adjective, self.separator, name
+ ),
+ };
+
+ Ok(result)
+ }
+}
+
+pub fn new_petname(num_words: i32, separator: &str) -> Result, PetnameError> {
+ let num_words = match num_words {
+ 1 => NumWords::One,
+ 2 => NumWords::Two,
+ 3 => NumWords::Three,
+ _ => return Err(PetnameError::InvalidNumWords(num_words)),
+ };
+ Ok(Box::new(Petname::new(num_words, separator)))
+}
+
+pub fn make_name(petname: &mut Petname) -> Result {
+ petname.make_name()
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/petname/names.txt b/crates/rustipass/src/petname/names.txt
similarity index 100%
rename from src/petname/names.txt
rename to crates/rustipass/src/petname/names.txt
diff --git a/crates/rustipass/src/petname/tests.rs b/crates/rustipass/src/petname/tests.rs
new file mode 100644
index 0000000000..9f0bd5cf1b
--- /dev/null
+++ b/crates/rustipass/src/petname/tests.rs
@@ -0,0 +1,108 @@
+use super::*;
+use std::collections::HashSet;
+
+fn split_name<'a>(name: &'a str, separator: &str) -> Vec<&'a str> {
+ name.split(separator).collect()
+}
+
+#[test]
+fn generates_the_requested_num_words() {
+ let mut gen1 = new_petname(1, "-").expect("Should create valid petname");
+ let mut gen2 = new_petname(2, "-").expect("Should create valid petname");
+ let mut gen3 = new_petname(3, "-").expect("Should create valid petname");
+
+ let one_word_name = make_name(&mut gen1).expect("Should generate name");
+ let tokens = split_name(&one_word_name, "-");
+ assert_eq!(tokens.len(), 1);
+ assert!(tokens.iter().all(|t| !t.is_empty()));
+
+ let two_word_name = make_name(&mut gen2).expect("Should generate name");
+ let tokens = split_name(&two_word_name, "-");
+ assert_eq!(tokens.len(), 2);
+ assert!(tokens.iter().all(|t| !t.is_empty()));
+
+ let three_word_name = make_name(&mut gen3).expect("Should generate name");
+ let tokens = split_name(&three_word_name, "-");
+ assert_eq!(tokens.len(), 3);
+ assert!(tokens.iter().all(|t| !t.is_empty()));
+}
+
+#[test]
+fn uses_custom_separator() {
+ let mut name_generator = new_petname(3, "_").expect("Should create valid petname");
+ let name = make_name(&mut name_generator).expect("Should generate name");
+ let tokens = split_name(&name, "_");
+ assert_eq!(tokens.len(), 3);
+ assert!(tokens.iter().all(|t| !t.is_empty()));
+ assert!(name.contains("_"));
+}
+
+#[test]
+fn can_generate_two_token_name() {
+ let mut name_generator = new_petname(2, "-").expect("Should create valid petname");
+ let name = make_name(&mut name_generator).expect("Should generate name");
+ let tokens = split_name(&name, "-");
+ assert_eq!(tokens.len(), 2);
+ assert!(tokens.iter().all(|t| !t.is_empty()));
+
+ // Each token should be unique
+ let unique_tokens: HashSet<_> = tokens.iter().collect();
+ assert_eq!(unique_tokens.len(), tokens.len());
+}
+
+#[test]
+fn can_generate_at_least_hundred_unique_names() {
+ let mut name_generator = new_petname(3, "-").expect("Should create valid petname");
+ let mut name_set = HashSet::new();
+ let expected_num_unique_names = 100;
+
+ // Generate many names to test uniqueness
+ for _ in 0..(10 * expected_num_unique_names) {
+ let name = make_name(&mut name_generator).expect("Should generate name");
+ name_set.insert(name);
+ }
+
+ assert!(name_set.len() >= expected_num_unique_names);
+}
+
+#[test]
+fn ffi_integration_test() {
+ let mut petname = new_petname(2, "-").expect("Should create valid petname");
+ let name = make_name(&mut petname).expect("Should generate name");
+ assert!(name.contains("-"));
+ assert!(!name.is_empty());
+}
+
+// error path tests
+#[test]
+fn new_petname_rejects_invalid_word_counts() {
+ assert!(new_petname(0, "-").is_err());
+ assert!(new_petname(4, "-").is_err());
+ assert!(new_petname(-1, "-").is_err());
+ assert!(new_petname(100, "-").is_err());
+}
+
+#[test]
+fn new_petname_returns_specific_error_for_invalid_counts() {
+ let result = new_petname(0, "-");
+ assert!(result.is_err());
+ let error = result.unwrap_err();
+ assert!(matches!(error, PetnameError::InvalidNumWords(0)));
+
+ let result = new_petname(5, "-");
+ assert!(result.is_err());
+ let error = result.unwrap_err();
+ assert!(matches!(error, PetnameError::InvalidNumWords(5)));
+}
+
+#[test]
+fn error_display_formatting() {
+ let error = PetnameError::InvalidNumWords(42);
+ assert_eq!(
+ error.to_string(),
+ "Invalid number of words: 42. Must be 1, 2, or 3"
+ );
+
+ let error = PetnameError::EmptyWordList("test".to_string());
+ assert_eq!(error.to_string(), "Empty word list: test");
+}
diff --git a/include/multipass/name_generator.h b/include/multipass/name_generator.h
index 7f607896e4..2f2dc67b5d 100644
--- a/include/multipass/name_generator.h
+++ b/include/multipass/name_generator.h
@@ -13,29 +13,21 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
- * Authored by: Alberto Aguirre
- *
*/
#pragma once
-#include "disabled_copy_move.h"
-
-#include
#include
namespace multipass
{
-class NameGenerator : private DisabledCopyMove
+
+class NameGenerator
{
public:
- using UPtr = std::unique_ptr;
virtual ~NameGenerator() = default;
- virtual std::string make_name() = 0;
-protected:
- NameGenerator() = default;
+ virtual std::string make_name() = 0;
};
-NameGenerator::UPtr make_default_name_generator();
} // namespace multipass
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 308199db62..7af102b4e6 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -203,6 +203,14 @@ parts:
- -DMULTIPASS_UPSTREAM=origin
- -DMULTIPASS_ENABLE_FLUTTER_GUI=on
override-build: |
+ # Install Rust stable toolchain
+ if [ ! -f "$HOME/.cargo/env" ]; then
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
+ source $HOME/.cargo/env
+ fi
+ # Ensure Rust is in PATH for this build
+ export PATH="$HOME/.cargo/bin:$PATH"
+
craftctl default
set -e
mkdir -p ${CRAFT_PART_INSTALL}/etc/bash_completion.d/
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7aa0f0c179..e25b8027ad 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,10 +24,10 @@ add_subdirectory(daemon)
add_subdirectory(iso)
add_subdirectory(logging)
add_subdirectory(network)
-add_subdirectory(petname)
add_subdirectory(platform)
add_subdirectory(process)
add_subdirectory(rpc)
+add_subdirectory(rustipass)
add_subdirectory(settings)
add_subdirectory(simplestreams)
add_subdirectory(ssh)
diff --git a/src/client/gui/ffi/dart_ffi.cpp b/src/client/gui/ffi/dart_ffi.cpp
index 7050de1ae0..e11fa35d81 100644
--- a/src/client/gui/ffi/dart_ffi.cpp
+++ b/src/client/gui/ffi/dart_ffi.cpp
@@ -1,14 +1,32 @@
+/*
+ * Copyright (C) Canonical, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
#include "multipass/dart_ffi.h"
#include "multipass/cli/client_common.h"
#include "multipass/logging/log.h"
#include "multipass/memory_size.h"
-#include "multipass/name_generator.h"
#include "multipass/platform.h"
#include "multipass/settings/settings.h"
#include "multipass/standard_paths.h"
#include "multipass/utils.h"
#include "multipass/version.h"
+#include
+
#include
namespace mp = multipass;
@@ -32,9 +50,10 @@ char* generate_petname()
static constexpr auto error = "failed generating petname";
try
{
- static mp::NameGenerator::UPtr generator = mp::make_default_name_generator();
- const auto name = generator->make_name();
- return strdup(name.c_str());
+ static rust::Box generator =
+ multipass::petname::new_petname(2, "-");
+ const auto name = multipass::petname::make_name(*generator);
+ return strdup(std::string(name).c_str());
}
catch (const std::exception& e)
{
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index d436d25b0d..0206c614c7 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -37,7 +37,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -56,6 +55,8 @@
#include
#include
+#include
+
#include
#include
@@ -211,12 +212,15 @@ auto name_from(const std::string& requested_name,
}
else
{
- auto name = name_gen.make_name();
+ std::string name = name_generator.make_name();
constexpr int num_retries = 100;
for (int i = 0; i < num_retries; i++)
{
if (currently_used_names.find(name) != currently_used_names.end())
+ {
+ name = name_generator.make_name();
continue;
+ }
return name;
}
throw std::runtime_error("unable to generate a unique name");
diff --git a/src/daemon/daemon_config.cpp b/src/daemon/daemon_config.cpp
index 776d1f4aec..0d2c9017a6 100644
--- a/src/daemon/daemon_config.cpp
+++ b/src/daemon/daemon_config.cpp
@@ -20,11 +20,12 @@
#include "custom_image_host.h"
#include "ubuntu_image_host.h"
+#include
+
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -198,8 +199,6 @@ std::unique_ptr mp::DaemonConfigBuilder::build()
factory->get_backend_directory_name()),
days_to_expire);
}
- if (name_generator == nullptr)
- name_generator = mp::make_default_name_generator();
if (server_address.empty())
server_address = platform::default_server_address();
if (ssh_key_provider == nullptr)
@@ -237,17 +236,20 @@ std::unique_ptr mp::DaemonConfigBuilder::build()
fs::perms::others_exec),
server_name_from(server_address));
+ if (name_generator == nullptr)
+ name_generator = std::make_unique();
+
return std::unique_ptr(new DaemonConfig{std::move(url_downloader),
std::move(factory),
std::move(image_hosts),
std::move(vault),
- std::move(name_generator),
std::move(ssh_key_provider),
std::move(cert_provider),
std::move(client_cert_store),
std::move(update_prompt),
multiplexing_logger,
std::move(network_proxy),
+ std::move(name_generator),
cache_directory,
data_directory,
server_address,
diff --git a/src/daemon/daemon_config.h b/src/daemon/daemon_config.h
index f91e5f748b..ea7bd5cb6d 100644
--- a/src/daemon/daemon_config.h
+++ b/src/daemon/daemon_config.h
@@ -46,13 +46,13 @@ struct DaemonConfig
const std::unique_ptr factory;
const std::vector> image_hosts;
const std::unique_ptr vault;
- const std::unique_ptr name_generator;
const std::unique_ptr ssh_key_provider;
const std::unique_ptr cert_provider;
const std::unique_ptr client_cert_store;
const std::unique_ptr update_prompt;
const std::shared_ptr logger;
const std::unique_ptr network_proxy;
+ const std::unique_ptr name_generator;
const multipass::Path cache_directory;
const multipass::Path data_directory;
const std::string server_address;
@@ -66,13 +66,13 @@ struct DaemonConfigBuilder
std::unique_ptr factory;
std::vector> image_hosts;
std::unique_ptr vault;
- std::unique_ptr name_generator;
std::unique_ptr ssh_key_provider;
std::unique_ptr cert_provider;
std::unique_ptr client_cert_store;
std::unique_ptr update_prompt;
std::unique_ptr logger;
std::unique_ptr network_proxy;
+ std::unique_ptr name_generator;
multipass::Path cache_directory;
multipass::Path data_directory;
std::string server_address;
diff --git a/src/petname/CMakeLists.txt b/src/petname/CMakeLists.txt
deleted file mode 100644
index eb59e3e9d6..0000000000
--- a/src/petname/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) Canonical, Ltd.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-# Authored by: Alberto Aguirre
-
-set(PETNAME_GENERATED_SOURCE_DIR ${MULTIPASS_GENERATED_SOURCE_DIR}/multipass/petname)
-set(PETNAME_GENERATED_HEADER ${PETNAME_GENERATED_SOURCE_DIR}/names.h)
-file(MAKE_DIRECTORY ${PETNAME_GENERATED_SOURCE_DIR})
-
-add_executable(text_to_string_array
- text_to_string_array.cpp)
-
-add_custom_command(
- OUTPUT "${PETNAME_GENERATED_HEADER}"
- COMMAND $
- ARGS ${CMAKE_CURRENT_SOURCE_DIR}/adjectives.txt ${CMAKE_CURRENT_SOURCE_DIR}/adverbs.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/names.txt ${PETNAME_GENERATED_HEADER}
- DEPENDS text_to_string_array
- COMMENT "Converting petnames to c++ header"
- VERBATIM)
-
-set_source_files_properties(${PETNAME_GENERATED_HEADER} PROPERTIES GENERATED TRUE)
-
-add_library(petname STATIC
- ${PETNAME_GENERATED_HEADER}
- petname.cpp
- make_name_generator.cpp)
diff --git a/src/petname/petname.cpp b/src/petname/petname.cpp
deleted file mode 100644
index 2334532175..0000000000
--- a/src/petname/petname.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) Canonical, Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * Authored by: Alberto Aguirre
- *
- */
-
-#include "petname.h"
-#include "multipass/petname/names.h"
-
-#include
-
-namespace mp = multipass;
-namespace
-{
-constexpr auto num_names = std::extent::value;
-constexpr auto num_adverbs = std::extent::value;
-constexpr auto num_adjectives = std::extent::value;
-
-// Arbitrary but arrays should have at least 100 entries each
-static_assert(num_names >= 100, "");
-static_assert(num_adverbs >= 100, "");
-static_assert(num_adjectives >= 100, "");
-
-std::mt19937 make_engine()
-{
- std::random_device device;
- return std::mt19937(device());
-}
-} // namespace
-
-mp::Petname::Petname(std::string separator) : Petname(NumWords::TWO, separator)
-{
-}
-
-mp::Petname::Petname(NumWords num_words) : Petname(num_words, "-")
-{
-}
-
-mp::Petname::Petname(NumWords num_words, std::string separator)
- : separator{separator},
- num_words{num_words},
- engine{make_engine()},
- name_dist{1, num_names - 1},
- adjective_dist{0, num_adjectives - 1},
- adverb_dist{0, num_adverbs - 1}
-{
-}
-
-std::string mp::Petname::make_name()
-{
- std::string name = multipass::petname::names[name_dist(engine)];
- std::string adjective = multipass::petname::adjectives[adjective_dist(engine)];
- std::string adverb = multipass::petname::adverbs[adverb_dist(engine)];
-
- switch (num_words)
- {
- case NumWords::ONE:
- return name;
- case NumWords::TWO:
- return adjective + separator + name;
- case NumWords::THREE:
- return adverb + separator + adjective + separator + name;
- default:
- throw std::invalid_argument("Invalid number of words chosen");
- }
-}
diff --git a/src/petname/petname.h b/src/petname/petname.h
deleted file mode 100644
index 43838cce85..0000000000
--- a/src/petname/petname.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) Canonical, Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * Authored by: Alberto Aguirre
- *
- */
-
-#pragma once
-
-#include
-
-#include
-#include
-#include
-
-namespace multipass
-{
-class Petname final : public NameGenerator
-{
-public:
- enum class NumWords
- {
- ONE,
- TWO,
- THREE
- };
-
- /// Constructs an instance that will generate names using
- /// the requested separator and the requested number of words
- Petname(NumWords num_words, std::string separator);
- /// Constructs an instance that will generate names using
- /// a default separator of "-" and the requested number of words
- explicit Petname(NumWords num_words);
- /// Constructs an instance that will generate names using
- /// the requested separator and two words
- explicit Petname(std::string separator);
-
- std::string make_name() override;
-
-private:
- std::string separator;
- NumWords num_words;
- std::mt19937 engine;
- std::uniform_int_distribution name_dist;
- std::uniform_int_distribution adjective_dist;
- std::uniform_int_distribution adverb_dist;
-};
-} // namespace multipass
diff --git a/src/petname/text_to_string_array.cpp b/src/petname/text_to_string_array.cpp
deleted file mode 100644
index dd296f3b6e..0000000000
--- a/src/petname/text_to_string_array.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) Canonical, Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * Authored by: Alberto Aguirre
- *
- */
-
-#include
-#include
-#include
-#include
-
-namespace
-{
-void usage(char* argv[])
-{
- std::cout << "Usage:\n ";
- std::cout << argv[0] << "