diff --git a/.agents/codebase-insights.txt b/.agents/codebase-insights.txt index eddcaad05..406da9a61 100644 --- a/.agents/codebase-insights.txt +++ b/.agents/codebase-insights.txt @@ -11,7 +11,6 @@ `get_message()`, so callers need to drain messages until `None` after feeding new bytes. - - The db-backend DAP server now responds to the `configurationDone` request. - Electron lifecycle: the backend-manager process is spawned in @@ -20,3 +19,5 @@ and hook it to `app.on('before-quit')`, `app.on('window-all-closed')`, and Node process signals (`SIGINT`, `SIGTERM`, `SIGHUP`) to ensure the process is always terminated when the app exits. +- The CodeTracer frontend and tooling now invoke the legacy CLI via the + `ct-legacy` binary; avoid calling the `ct` binary because it is a different tool. diff --git a/appimage-scripts/build_appimage.sh b/appimage-scripts/build_appimage.sh index dbe4ace1a..88a1c3b09 100755 --- a/appimage-scripts/build_appimage.sh +++ b/appimage-scripts/build_appimage.sh @@ -104,14 +104,14 @@ bash "${ROOT_PATH}"/appimage-scripts/build_css.sh # Build/setup nim-based files bash "${ROOT_PATH}"/appimage-scripts/build_with_nim.sh -cat << 'EOF' > "${APP_DIR}/bin/ct" +cat << 'EOF' > "${APP_DIR}/bin/ct-legacy" #!/usr/bin/env bash HERE=${HERE:-$(dirname "$(readlink -f "${0}")")} # TODO: This includes references to x86_64. What about aarch64? -exec "${HERE}"/bin/ct_unwrapped "$@" +exec "${HERE}"/bin/ct-legacy_unwrapped "$@" EOF @@ -204,7 +204,7 @@ export LINKS_PATH_DIR=$HERE export PATH="${HERE}/bin:${PATH}" export CODETRACER_RUBY_RECORDER_PATH="${HERE}/codetracer-ruby-recorder/gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder" -exec ${HERE}/bin/ct "$@" +exec ${HERE}/bin/ct-legacy "$@" EOF chmod +x "${APP_DIR}/AppRun" @@ -252,7 +252,7 @@ else fi # Patchelf the executable's interpreter -patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/ct_unwrapped +patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/ct-legacy_unwrapped patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/db-backend patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/db-backend-record patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/backend-manager @@ -265,7 +265,7 @@ patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/bin/node patchelf --set-interpreter "${INTERPRETER_PATH}" "${APP_DIR}"/ruby/bin/ruby # Clear up the executable's rpath -patchelf --remove-rpath "${APP_DIR}"/bin/ct_unwrapped +patchelf --remove-rpath "${APP_DIR}"/bin/ct-legacy_unwrapped patchelf --remove-rpath "${APP_DIR}"/bin/db-backend patchelf --remove-rpath "${APP_DIR}"/bin/db-backend-record patchelf --remove-rpath "${APP_DIR}"/bin/backend-manager @@ -277,7 +277,7 @@ patchelf --remove-rpath "${APP_DIR}"/bin/node patchelf --remove-rpath "${APP_DIR}"/ruby/bin/ruby patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/node -patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/ct_unwrapped +patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/ct-legacy_unwrapped patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/db-backend patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/db-backend-record patchelf --set-rpath "\$ORIGIN/../lib" "${APP_DIR}"/bin/backend-manager diff --git a/appimage-scripts/build_with_nim.sh b/appimage-scripts/build_with_nim.sh index 19ca8e22d..693ec1ade 100755 --- a/appimage-scripts/build_with_nim.sh +++ b/appimage-scripts/build_with_nim.sh @@ -46,7 +46,7 @@ nim -d:release \ -d:libcPath=libc \ -d:pathToNodeModules=../node_modules \ --nimcache:nimcache \ - --out:"${APP_DIR}/bin/ct_unwrapped" c ./src/ct/codetracer.nim + --out:"${APP_DIR}/bin/ct-legacy_unwrapped" c ./src/ct-legacy/codetracer.nim nim \ @@ -70,7 +70,7 @@ nim \ --passL:"${APP_DIR}/lib/libpcre.so.1" \ --passL:"${APP_DIR}/lib/libzip.so.5" \ --nimcache:nimcache \ - --out:"${APP_DIR}/bin/db-backend-record" c ./src/ct/db_backend_record.nim + --out:"${APP_DIR}/bin/db-backend-record" c ./src/ct-legacy/db_backend_record.nim # --passL:"-lsqlite3" \ #--passL:"${APPDIR}/lib/libcrypto.so.3" \ @@ -81,7 +81,7 @@ nim \ # TODO conditional for nixos?--passL:$LIBSQLITE3_PATH # -# patchelf --set-rpath ${APP_DIR}/lib ${APP_DIR}/bin/ct +# patchelf --set-rpath ${APP_DIR}/lib ${APP_DIR}/bin/ct-legacy # index.js diff --git a/docs/book/src/installation.md b/docs/book/src/installation.md index c754990f9..8fd51fa03 100644 --- a/docs/book/src/installation.md +++ b/docs/book/src/installation.md @@ -59,7 +59,7 @@ Direnv should be set up in your shell, as shown [here](https://direnv.net/docs/h ``` 4. Run `nix develop` 5. Run `direnv allow` -6. To build codetracer simply run `just build`. The location of the resulting binary will be `./src/build-debug/bin/ct` +6. To build codetracer simply run `just build`. The location of the resulting binary will be `./src/build-debug/bin/ct-legacy` 7. Now every time you enter the `codetracer` directory your environment should be updated > [!TIP] @@ -78,7 +78,7 @@ The only dependencies for the macOS build are `git`, `bash` and `homebrew`. 1. Clone the repository with submodules: `git clone https://github.com/metacraft-labs/codetracer.git --recursive` 2. Enter the created directory 3. Run `./non-nix-build/build.sh` from the root of the cloned repository. This will install all prerequisites like Rust, Nim and others using homebrew -4. The resulting binary can be found at `./non-nix-build/CodeTracer.app/Contents/MacOS/bin/ct`, and a DMG installer is created at `./non-nix-build/CodeTracer.dmg`. +4. The resulting binary can be found at `./non-nix-build/CodeTracer.app/Contents/MacOS/bin/ct-legacy`, and a DMG installer is created at `./non-nix-build/CodeTracer.dmg`. ### Building and running the tests diff --git a/nix/packages/default.nix b/nix/packages/default.nix index 08c98c651..87a7e6f69 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -623,7 +623,7 @@ mkdir -p $out/frontend/styles - cp ./ct $out/bin/ + cp ./ct-legacy $out/bin/ # Codetracer web cp -L ${codetracer-electron}/views/server_index.ejs $out/views @@ -660,7 +660,7 @@ cp -L ${codetracer-electron}/src/helpers.js $out/src/helpers.js # ln -sf ${codetracer-electron}/src/public/ $out/public - cp ./ct $out/bin + cp ./ct-legacy $out/bin cp ./db-backend-record $out/bin cp -r src/frontend/index.html $out/ @@ -668,10 +668,10 @@ ''; - meta.mainProgram = "ct"; + meta.mainProgram = "ct-legacy"; postFixup = '' - wrapProgram $out/bin/ct \ + wrapProgram $out/bin/ct-legacy \ --prefix PATH : ${pkgs.lib.makeBinPath [ cargo-stylus ]} ''; diff --git a/non-nix-build/build_in_simple_env.sh b/non-nix-build/build_in_simple_env.sh index 6eb7a2e27..db1542f06 100755 --- a/non-nix-build/build_in_simple_env.sh +++ b/non-nix-build/build_in_simple_env.sh @@ -56,19 +56,19 @@ cp -r "$ROOT_DIR"/src/config "$DIST_DIR"/config cp -r "$ROOT_DIR"/src/public "$DIST_DIR"/public cp -r "$BIN_DIR"/* "$DIST_DIR"/bin/ -mv "$DIST_DIR"/bin/ct "$DIST_DIR"/bin/ct_unwrapped +mv "$DIST_DIR"/bin/ct-legacy "$DIST_DIR"/bin/ct-legacy_unwrapped -cat << 'EOF' > "${DIST_DIR}"/bin/ct +cat << 'EOF' > "${DIST_DIR}"/bin/ct-legacy #!/usr/bin/env bash export HERE=$(dirname $(dirname "$0")) export CODETRACER_RUBY_RECORDER_PATH="${HERE}/codetracer-ruby-recorder/gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder" -exec ${HERE}/bin/ct_unwrapped "$@" +exec ${HERE}/bin/ct-legacy_unwrapped "$@" EOF -chmod +x "${DIST_DIR}"/bin/ct +chmod +x "${DIST_DIR}"/bin/ct-legacy # Enable the installation prompt. Extra argument to be compatible with FreeBSD coreutils sed -i "" "s/skipInstall.*/skipInstall: false/g" "$DIST_DIR/config/default_config.yaml" diff --git a/non-nix-build/build_mac_app.sh b/non-nix-build/build_mac_app.sh index 05b0e9ef7..b398135e8 100755 --- a/non-nix-build/build_mac_app.sh +++ b/non-nix-build/build_mac_app.sh @@ -27,6 +27,6 @@ cp "$DIST_DIR"/../Resources/CodeTracer.icns "$(realpath MacOS/node_modules)"/ele # macOS uses core utils from FreeBSD so the additional "" is needed to execute this sed call. # # This sed call is needed because even though we replaced the entire plist file, the CodeTracer icon will not be displayed correctly -# in the auto-generated about menu, if the correct executable isn't listed here. If it was left as "bin/ct" a big disabled icon would +# in the auto-generated about menu, if the correct executable isn't listed here. If it was left as "bin/ct-legacy" a big disabled icon would # be overlayed on top of the app icon -sed -i "" "s/\bin\/ct/\Electron/g" "$(realpath MacOS/node_modules)"/electron/dist/Electron.app/Contents/Info.plist +sed -i "" "s/\bin\/ct-legacy/\Electron/g" "$(realpath MacOS/node_modules)"/electron/dist/Electron.app/Contents/Info.plist diff --git a/non-nix-build/build_with_nim.sh b/non-nix-build/build_with_nim.sh index f5923c8ac..13f423fd2 100755 --- a/non-nix-build/build_with_nim.sh +++ b/non-nix-build/build_with_nim.sh @@ -35,15 +35,15 @@ nim -d:release \ -d:ctEntrypoint \ --nimcache:nimcache \ -d:ctmacos \ - --out:"$DIST_DIR/bin/ct" c ./src/ct/codetracer.nim + --out:"$DIST_DIR/bin/ct-legacy" c ./src/ct-legacy/codetracer.nim install_name_tool \ -add_rpath "@executable_path/../../Frameworks" \ - "${DIST_DIR}/bin/ct" + "${DIST_DIR}/bin/ct-legacy" -install_name_tool -add_rpath "@loader_path" "${DIST_DIR}/bin/ct" +install_name_tool -add_rpath "@loader_path" "${DIST_DIR}/bin/ct-legacy" -codesign -s - --force --deep "${DIST_DIR}/bin/ct" +codesign -s - --force --deep "${DIST_DIR}/bin/ct-legacy" nim -d:release \ -d:asyncBackend=asyncdispatch \ @@ -60,7 +60,7 @@ nim -d:release \ -d:ctEntrypoint \ --nimcache:nimcache \ -d:ctmacos \ - --out:"$DIST_DIR/bin/db-backend-record" c ./src/ct/db_backend_record.nim + --out:"$DIST_DIR/bin/db-backend-record" c ./src/ct-legacy/db_backend_record.nim install_name_tool \ -add_rpath "@executable_path/../../Frameworks" \ diff --git a/resources/Info.plist b/resources/Info.plist index 3e93ad006..f61fd8cd5 100644 --- a/resources/Info.plist +++ b/resources/Info.plist @@ -6,7 +6,7 @@ CodeTracer CFBundleExecutable - bin/ct + bin/ct-legacy CFBundleIconFile CodeTracer.icns @@ -83,4 +83,3 @@ Copyright (c) 2025 Metacraft Labs Ltd. - diff --git a/resources/codetracer.desktop b/resources/codetracer.desktop index 47289aa50..da3484c22 100644 --- a/resources/codetracer.desktop +++ b/resources/codetracer.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Version=1.0 Type=Application -Exec=ct +Exec=ct-legacy Name=CodeTracer Name[ja]=コードトレーサ始める Comment=A user-friendly time-travelling debugger designed to support a wide range of programming languages. @@ -9,4 +9,3 @@ Icon=codetracer Categories=Development Keywords=codetracer;time-travelling;debugger;omniscient;noir;nargo;tracing StartupWMClass=CodeTracer - diff --git a/src/Tuprules.tup b/src/Tuprules.tup index 64e9b9523..a83f736c4 100644 --- a/src/Tuprules.tup +++ b/src/Tuprules.tup @@ -155,6 +155,10 @@ export RUSTUP_HOME CARGO_TARGET_DIR=/tmp/codetracer/backend_manager_target \ cargo build --release && \ cp /tmp/codetracer/backend_manager_target/release/backend-manager %o |> %o +!rust_cargo_ct = |> \ + CARGO_TARGET_DIR=/tmp/codetracer/ct_target \ + cargo build --release && \ + cp /tmp/codetracer/ct_target/release/ct %o |> %o !debug_rust_cargo_db_backend = |> \ CARGO_TARGET_DIR=/tmp/codetracer/db_backend_target \ cargo build && \ diff --git a/src/common/install_utils.nim b/src/common/install_utils.nim index 435c74d13..3e12720f8 100644 --- a/src/common/install_utils.nim +++ b/src/common/install_utils.nim @@ -103,16 +103,16 @@ proc installCodetracerOnPath*(codetracerExe: string): Result[void, string] {.rai execPath = getEnv("APPIMAGE") try: - if not fileExists(binDir / "ct"): + if not fileExists(binDir / "ct-legacy"): echo fmt2"Creating symlink to {execPath} in {binDir}" - createSymlink(execPath, binDir / "ct") + createSymlink(execPath, binDir / "ct-legacy") - elif isSymlinkDangling(binDir / "ct"): + elif isSymlinkDangling(binDir / "ct-legacy"): # Try and clean up the installation - removeFile(binDir / "ct") - createSymlink(execPath, binDir / "ct") + removeFile(binDir / "ct-legacy") + createSymlink(execPath, binDir / "ct-legacy") else: - echo fmt2"{binDir}/ct already exists and is not dangling" + echo fmt2"{binDir}/ct-legacy already exists and is not dangling" except OSError as e: return err "Failed to put CodeTracer on the PATH: " & e.msg @@ -126,13 +126,13 @@ proc installCodetracerOnPath*(codetracerExe: string): Result[void, string] {.rai try: createDir(shellLaunchersDir) - let ctLauncherPath = shellLaunchersDir / "ct" - writeFile(ctLauncherPath, slurpShellIntegrationFile "shell-launchers/ct") + let ctLauncherPath = shellLaunchersDir / "ct-legacy" + writeFile(ctLauncherPath, slurpShellIntegrationFile "shell-launchers/ct-legacy") setFilePermissions(ctLauncherPath, {fpUserExec, fpGroupExec, fpOthersExec, fpUserRead, fpGroupRead, fpOthersRead, fpUserWrite}) except CatchableError as err: - return err "Failed to create the ct shell launcher: " & err.msg + return err "Failed to create the ct-legacy shell launcher: " & err.msg let shellPath = getEnv("SHELL", "/bin/bash") @@ -253,7 +253,7 @@ when defined(linux): # ran the `install` command echo fmt"Replacing exec field with {execPath}" - contents = contents.replace("Exec=ct", fmt"Exec={execPath}") + contents = contents.replace("Exec=ct-legacy", fmt"Exec={execPath}") let desktopFile = desktopFileDir / "codetracer.desktop" diff --git a/src/common/paths.nim b/src/common/paths.nim index dc18f56e5..8b3d0e3e2 100644 --- a/src/common/paths.nim +++ b/src/common/paths.nim @@ -73,7 +73,7 @@ let cTraceSourcePath* = linksPath / "src" / "trace.c" consoleExe* = linksPath / "bin" / "console" # (additional note: it is a workaround for dev/some cases: TODO think more) - codetracerExe* = codetracerExeDir / "bin" / "ct" + codetracerExe* = codetracerExeDir / "bin" / "ct-legacy" bashExe* = linksPath / "bin" / "bash" taskProcessExe* = linksPath / "bin" / "task_process" python3Path* = linksPath / "bin" / "python3" @@ -139,7 +139,7 @@ let nodeModulesPath* = linksPath / "node_modules" codetracerTestDir* = codetracerInstallDir / "src" / "tests" - codetracerNixResultExe* = codetracerInstallDir / "result" / "bin" / "ct" + codetracerNixResultExe* = codetracerInstallDir / "result" / "bin" / "ct-legacy" codetracerTestBuildDir* = codetracerExeDir / "tests" programDir* = codetracerTestDir / "programs" recordDir* = codetracerTestDir / "records" diff --git a/src/ct/version.nim b/src/common/version.nim similarity index 100% rename from src/ct/version.nim rename to src/common/version.nim diff --git a/src/ct-legacy/Tupfile b/src/ct-legacy/Tupfile new file mode 100644 index 000000000..4ac4aef51 --- /dev/null +++ b/src/ct-legacy/Tupfile @@ -0,0 +1,7 @@ +include_rules + +: codetracer.nim |> !codetracer |> ../bin/codetracer_depending_on_env_vars_in_tup +: ct_wrapper.nim |> !nim_c |> ../bin/ct-legacy +# TODO think if we want explicitly both +# : ct_wrapper.nim |> !nim_c |> ../bin/codetracer +: db_backend_record.nim |> !codetracer |> ../bin/db-backend-record diff --git a/src/ct/cli/build.nim b/src/ct-legacy/cli/build.nim similarity index 100% rename from src/ct/cli/build.nim rename to src/ct-legacy/cli/build.nim diff --git a/src/ct/cli/help.nim b/src/ct-legacy/cli/help.nim similarity index 100% rename from src/ct/cli/help.nim rename to src/ct-legacy/cli/help.nim diff --git a/src/ct/cli/interactive_replay.nim b/src/ct-legacy/cli/interactive_replay.nim similarity index 100% rename from src/ct/cli/interactive_replay.nim rename to src/ct-legacy/cli/interactive_replay.nim diff --git a/src/ct/cli/list.nim b/src/ct-legacy/cli/list.nim similarity index 100% rename from src/ct/cli/list.nim rename to src/ct-legacy/cli/list.nim diff --git a/src/ct/cli/logging.nim b/src/ct-legacy/cli/logging.nim similarity index 100% rename from src/ct/cli/logging.nim rename to src/ct-legacy/cli/logging.nim diff --git a/src/ct/codetracer.nim b/src/ct-legacy/codetracer.nim similarity index 97% rename from src/ct/codetracer.nim rename to src/ct-legacy/codetracer.nim index 209f022d8..5dafaa9eb 100644 --- a/src/ct/codetracer.nim +++ b/src/ct-legacy/codetracer.nim @@ -3,7 +3,7 @@ import launch/[ launch ], codetracerconf, confutils, - version + ../common/version try: if not eventuallyWrapElectron(): diff --git a/src/ct/codetracerconf.nim b/src/ct-legacy/codetracerconf.nim similarity index 100% rename from src/ct/codetracerconf.nim rename to src/ct-legacy/codetracerconf.nim diff --git a/src/ct/ct_wrapper.nim b/src/ct-legacy/ct_wrapper.nim similarity index 100% rename from src/ct/ct_wrapper.nim rename to src/ct-legacy/ct_wrapper.nim diff --git a/src/ct/db_backend_record.nim b/src/ct-legacy/db_backend_record.nim similarity index 100% rename from src/ct/db_backend_record.nim rename to src/ct-legacy/db_backend_record.nim diff --git a/src/ct/globals.nim b/src/ct-legacy/globals.nim similarity index 100% rename from src/ct/globals.nim rename to src/ct-legacy/globals.nim diff --git a/src/ct/launch/backends.nim b/src/ct-legacy/launch/backends.nim similarity index 100% rename from src/ct/launch/backends.nim rename to src/ct-legacy/launch/backends.nim diff --git a/src/ct/launch/cleanup.nim b/src/ct-legacy/launch/cleanup.nim similarity index 100% rename from src/ct/launch/cleanup.nim rename to src/ct-legacy/launch/cleanup.nim diff --git a/src/ct/launch/electron.nim b/src/ct-legacy/launch/electron.nim similarity index 100% rename from src/ct/launch/electron.nim rename to src/ct-legacy/launch/electron.nim diff --git a/src/ct/launch/launch.nim b/src/ct-legacy/launch/launch.nim similarity index 100% rename from src/ct/launch/launch.nim rename to src/ct-legacy/launch/launch.nim diff --git a/src/ct/online_sharing/delete.nim b/src/ct-legacy/online_sharing/delete.nim similarity index 100% rename from src/ct/online_sharing/delete.nim rename to src/ct-legacy/online_sharing/delete.nim diff --git a/src/ct/online_sharing/download.nim b/src/ct-legacy/online_sharing/download.nim similarity index 100% rename from src/ct/online_sharing/download.nim rename to src/ct-legacy/online_sharing/download.nim diff --git a/src/ct/online_sharing/online_sharing_test.nim b/src/ct-legacy/online_sharing/online_sharing_test.nim similarity index 100% rename from src/ct/online_sharing/online_sharing_test.nim rename to src/ct-legacy/online_sharing/online_sharing_test.nim diff --git a/src/ct/online_sharing/upload.nim b/src/ct-legacy/online_sharing/upload.nim similarity index 100% rename from src/ct/online_sharing/upload.nim rename to src/ct-legacy/online_sharing/upload.nim diff --git a/src/ct/sourcemap.nim b/src/ct-legacy/sourcemap.nim similarity index 100% rename from src/ct/sourcemap.nim rename to src/ct-legacy/sourcemap.nim diff --git a/src/ct/stylus/arb_node_utils.nim b/src/ct-legacy/stylus/arb_node_utils.nim similarity index 100% rename from src/ct/stylus/arb_node_utils.nim rename to src/ct-legacy/stylus/arb_node_utils.nim diff --git a/src/ct/stylus/deploy.nim b/src/ct-legacy/stylus/deploy.nim similarity index 100% rename from src/ct/stylus/deploy.nim rename to src/ct-legacy/stylus/deploy.nim diff --git a/src/ct/stylus/record.nim b/src/ct-legacy/stylus/record.nim similarity index 100% rename from src/ct/stylus/record.nim rename to src/ct-legacy/stylus/record.nim diff --git a/src/ct/thread_affinities.nim b/src/ct-legacy/thread_affinities.nim similarity index 100% rename from src/ct/thread_affinities.nim rename to src/ct-legacy/thread_affinities.nim diff --git a/src/ct/trace/host.nim b/src/ct-legacy/trace/host.nim similarity index 100% rename from src/ct/trace/host.nim rename to src/ct-legacy/trace/host.nim diff --git a/src/ct/trace/import_command.nim b/src/ct-legacy/trace/import_command.nim similarity index 100% rename from src/ct/trace/import_command.nim rename to src/ct-legacy/trace/import_command.nim diff --git a/src/ct/trace/metadata.nim b/src/ct-legacy/trace/metadata.nim similarity index 100% rename from src/ct/trace/metadata.nim rename to src/ct-legacy/trace/metadata.nim diff --git a/src/ct/trace/multitrace.nim b/src/ct-legacy/trace/multitrace.nim similarity index 100% rename from src/ct/trace/multitrace.nim rename to src/ct-legacy/trace/multitrace.nim diff --git a/src/ct/trace/record.nim b/src/ct-legacy/trace/record.nim similarity index 100% rename from src/ct/trace/record.nim rename to src/ct-legacy/trace/record.nim diff --git a/src/ct/trace/replay.nim b/src/ct-legacy/trace/replay.nim similarity index 100% rename from src/ct/trace/replay.nim rename to src/ct-legacy/trace/replay.nim diff --git a/src/ct/trace/run.nim b/src/ct-legacy/trace/run.nim similarity index 100% rename from src/ct/trace/run.nim rename to src/ct-legacy/trace/run.nim diff --git a/src/ct/trace/shell.nim b/src/ct-legacy/trace/shell.nim similarity index 100% rename from src/ct/trace/shell.nim rename to src/ct-legacy/trace/shell.nim diff --git a/src/ct/trace/storage_and_import.nim b/src/ct-legacy/trace/storage_and_import.nim similarity index 100% rename from src/ct/trace/storage_and_import.nim rename to src/ct-legacy/trace/storage_and_import.nim diff --git a/src/ct/utilities/encryption.nim b/src/ct-legacy/utilities/encryption.nim similarity index 100% rename from src/ct/utilities/encryption.nim rename to src/ct-legacy/utilities/encryption.nim diff --git a/src/ct/utilities/encryption_test.nim b/src/ct-legacy/utilities/encryption_test.nim similarity index 100% rename from src/ct/utilities/encryption_test.nim rename to src/ct-legacy/utilities/encryption_test.nim diff --git a/src/ct/utilities/env.nim b/src/ct-legacy/utilities/env.nim similarity index 100% rename from src/ct/utilities/env.nim rename to src/ct-legacy/utilities/env.nim diff --git a/src/ct/utilities/git.nim b/src/ct-legacy/utilities/git.nim similarity index 100% rename from src/ct/utilities/git.nim rename to src/ct-legacy/utilities/git.nim diff --git a/src/ct/utilities/language_detection.nim b/src/ct-legacy/utilities/language_detection.nim similarity index 100% rename from src/ct/utilities/language_detection.nim rename to src/ct-legacy/utilities/language_detection.nim diff --git a/src/ct/utilities/progress_update.nim b/src/ct-legacy/utilities/progress_update.nim similarity index 100% rename from src/ct/utilities/progress_update.nim rename to src/ct-legacy/utilities/progress_update.nim diff --git a/src/ct/utilities/types.nim b/src/ct-legacy/utilities/types.nim similarity index 100% rename from src/ct/utilities/types.nim rename to src/ct-legacy/utilities/types.nim diff --git a/src/ct/utilities/zip.nim b/src/ct-legacy/utilities/zip.nim similarity index 100% rename from src/ct/utilities/zip.nim rename to src/ct-legacy/utilities/zip.nim diff --git a/src/ct/utilities/zip_test.nim b/src/ct-legacy/utilities/zip_test.nim similarity index 100% rename from src/ct/utilities/zip_test.nim rename to src/ct-legacy/utilities/zip_test.nim diff --git a/src/ct/Cargo.lock b/src/ct/Cargo.lock new file mode 100644 index 000000000..c8c556b60 --- /dev/null +++ b/src/ct/Cargo.lock @@ -0,0 +1,359 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "cc" +version = "1.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "clap" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "ct" +version = "0.1.0" +dependencies = [ + "clap", + "rusqlite", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "libsqlite3-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rusqlite" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[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.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "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.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" diff --git a/src/ct/Cargo.toml b/src/ct/Cargo.toml new file mode 100644 index 000000000..210ac8d8c --- /dev/null +++ b/src/ct/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ct" +version = "0.1.0" +edition = "2024" + +[dependencies] +clap = { version = "4.5.49", features = ["derive"] } +# bundled feature statically links libsql +rusqlite = { version = "0.37.0", features = ["bundled"] } diff --git a/src/ct/Tupfile b/src/ct/Tupfile index 01fc81991..50beeaa42 100644 --- a/src/ct/Tupfile +++ b/src/ct/Tupfile @@ -1,7 +1,3 @@ include_rules -: codetracer.nim |> !codetracer |> ../bin/codetracer_depending_on_env_vars_in_tup -: ct_wrapper.nim |> !nim_c |> ../bin/ct -# TODO think if we want explicitly both -# : ct_wrapper.nim |> !nim_c |> ../bin/codetracer -: db_backend_record.nim |> !codetracer |> ../bin/db-backend-record +: |> !rust_cargo_ct |> ../bin/ct diff --git a/src/ct/src/db.rs b/src/ct/src/db.rs new file mode 100644 index 000000000..d172cb46f --- /dev/null +++ b/src/ct/src/db.rs @@ -0,0 +1,53 @@ +use std::sync::{LazyLock, Mutex}; + +use rusqlite::Connection; + +use crate::paths::CODETRACER_PATHS; + +pub static CONNECTION_MUTEX: LazyLock> = LazyLock::new(|| { + // TODO: better error handling maybe? (this is sufficient, but the errors aren't exactly user friendly) + // TODO: implement migrations + + let res = Mutex::new( + Connection::open( + CODETRACER_PATHS + .lock() + .unwrap() + .data_path + .join("trace_index.db"), + ) + .unwrap(), + ); + + { + let conn = res.lock().unwrap(); + conn.execute( + " + CREATE TABLE IF NOT EXISTS traces ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + program text, + args text, + compileCommand text, + env text, + workdir text, + output text, + sourceFolders text, + lowLevelFolder text, + outputFolder text, + lang integer, + imported integer, + shellID integer, + rrPid integer, + exitCode integer, + calltrace integer, + calltraceMode string, + date text, + ); + ", + (), + ) + .unwrap(); + } + + res +}); diff --git a/src/ct/src/lang.rs b/src/ct/src/lang.rs new file mode 100644 index 000000000..9fd7e4139 --- /dev/null +++ b/src/ct/src/lang.rs @@ -0,0 +1,22 @@ +use clap::ValueEnum; + +#[derive(ValueEnum, Clone, Debug)] +pub enum Lang { + Python, + Ruby, + Noir, + Wasm, + Small, +} + +impl ToString for Lang { + fn to_string(&self) -> String { + match self { + Lang::Python => String::from("python"), + Lang::Ruby => String::from("ruby"), + Lang::Noir => String::from("noir"), + Lang::Wasm => String::from("wasm"), + Lang::Small => String::from("small"), + } + } +} diff --git a/src/ct/src/main.rs b/src/ct/src/main.rs new file mode 100644 index 000000000..1bb6f0eb1 --- /dev/null +++ b/src/ct/src/main.rs @@ -0,0 +1,61 @@ +mod db; +mod lang; +mod paths; +mod subcommands; + +use clap::{Parser, Subcommand}; + +use crate::lang::Lang; + +#[derive(Debug, Parser)] +#[command( + name = "ct", + about = "TODO: write description", + version, + propagate_version = true +)] +pub struct Args { + /// Selects which operation to perform. + #[command(subcommand)] + pub command: Command, +} + +#[derive(Debug, clap::Args)] +pub struct RecordOptions { + /// Override the language of the project. Used to determine which recorder is used. + #[arg(short, long)] + pub lang: Option, + + /// Where to save the trace. + #[arg(short, long)] + pub output_folder: Option, + + /// Path to the program to record. + pub program: String, + + /// Arguments to pass to the program. + pub args: Vec, +} + +#[derive(Debug, Subcommand)] +pub enum Command { + /// Record the execution of a program + Record(RecordOptions), + + /// Lists all available external subcommands. + List, + + /// Defer execution to an external `ct-*` binary. + #[command(external_subcommand)] + External(Vec), +} + +fn main() { + let args = Args::parse(); + + match args.command { + Command::List => subcommands::run_list::(), + Command::External(args) => subcommands::run_external(&args), + Command::Record(options) => subcommands::run_record(options), + } +} diff --git a/src/ct/src/paths.rs b/src/ct/src/paths.rs new file mode 100644 index 000000000..9a6732842 --- /dev/null +++ b/src/ct/src/paths.rs @@ -0,0 +1,33 @@ +use std::env; +use std::path::PathBuf; +use std::sync::{LazyLock, Mutex}; + +pub struct Paths { + pub tmp_path: PathBuf, + pub client_socket_path: PathBuf, + pub socket_path: PathBuf, + pub data_path: PathBuf, +} + +impl Default for Paths { + fn default() -> Self { + let tmpdir: PathBuf = if cfg!(target_os = "macos") { + PathBuf::from(env::var("HOME").unwrap_or("/".to_string())) + .join("Library/Caches/com.codetracer.CodeTracer/") + } else { + env::temp_dir().join("codetracer/") + }; + + Self { + tmp_path: PathBuf::from(&tmpdir), + client_socket_path: PathBuf::from(&tmpdir).join("ct_client_socket"), + socket_path: PathBuf::from(&tmpdir).join("ct_socket"), + data_path: env::home_dir() + .unwrap_or(PathBuf::from("~")) + .join(".local/share/codetracer"), // TODO: handle non-UNIX stuff + } + } +} + +pub static CODETRACER_PATHS: LazyLock> = + LazyLock::new(|| Mutex::new(Paths::default())); diff --git a/src/ct/src/subcommands/external.rs b/src/ct/src/subcommands/external.rs new file mode 100644 index 000000000..58eb774b3 --- /dev/null +++ b/src/ct/src/subcommands/external.rs @@ -0,0 +1,53 @@ +use std::{ + env, + path::PathBuf, + process::{self, exit}, +}; + +pub fn run_external(args: &[String]) { + let name = &args[0]; + let exe_name = String::from("ct-") + name; + let args = &args[1..]; + + let exe = match resolve_executable(&exe_name) { + Some(exe) => exe, + None => { + println!( + "\"{name}\" subcommand not recognised (maybe you didn't install this module?)" + ); + exit(1) + } + }; + + let mut command = process::Command::new(exe); + command.args(args); + + let mut child = command.spawn().unwrap(); // TODO: handle error + exit(child.wait().unwrap().code().unwrap()) // TODO: handle errors +} + +fn resolve_executable(name: &str) -> Option { + // Check if this executable is present in the directory of the tool binary + let exe_dir = std::env::current_exe() + .ok() + .and_then(|x| x.parent().map(|x| x.to_path_buf())); + + if let Some(exe_dir) = exe_dir { + let subcommand_exe = exe_dir.join(name); + if subcommand_exe.is_file() { + return Some(subcommand_exe); + } + } + + // Try to resolve through PATH + if let Some(paths) = env::var_os("PATH") { + for dir in env::split_paths(&paths) { + let candidate = dir.join(name); + if candidate.is_file() { + return Some(candidate); + } + } + } + + None +} diff --git a/src/ct/src/subcommands/list.rs b/src/ct/src/subcommands/list.rs new file mode 100644 index 000000000..28bb7ef3d --- /dev/null +++ b/src/ct/src/subcommands/list.rs @@ -0,0 +1,48 @@ +use std::{collections::BTreeMap, env, fs, path::PathBuf}; + +pub fn run_list() { + let mut subcommands = get_external_subcommands(); + for subcommand in T::command().get_subcommands() { + subcommands.insert(subcommand.get_name().to_string(), "(internal)".to_string()); + } + subcommands.insert("help".to_string(), "(internal)".to_string()); + for (name, path) in subcommands { + println!("{name} => {path}"); + } +} + +fn get_external_subcommands() -> BTreeMap { + let mut res = BTreeMap::new(); + + // The priority of the path is proportional to its index in this vec + let mut dirs: Vec = vec![]; + + if let Some(paths) = env::var_os("PATH") { + dirs.extend(env::split_paths(&paths)); + dirs.reverse(); + } + + if let Some(exe_dir) = std::env::current_exe() + .ok() + .and_then(|x| x.parent().map(|x| x.to_path_buf())) + { + dirs.push(exe_dir); + } + + for dir in dirs { + if let Ok(dir_entries) = fs::read_dir(dir) { + for entry in dir_entries { + if let Ok(entry) = entry + && entry.path().is_file() + && let Some(name) = entry.path().file_name() + && let Some(name) = name.to_str() + && name.starts_with("ct-") + { + res.insert(String::from(&name[3..]), entry.path().display().to_string()); + } + } + } + } + + res +} diff --git a/src/ct/src/subcommands/mod.rs b/src/ct/src/subcommands/mod.rs new file mode 100644 index 000000000..301f5bb84 --- /dev/null +++ b/src/ct/src/subcommands/mod.rs @@ -0,0 +1,8 @@ +mod external; +pub use external::run_external; + +mod list; +pub use list::run_list; + +mod record; +pub use record::run_record; diff --git a/src/ct/src/subcommands/record.rs b/src/ct/src/subcommands/record.rs new file mode 100644 index 000000000..09e50881f --- /dev/null +++ b/src/ct/src/subcommands/record.rs @@ -0,0 +1,67 @@ +use std::{path::PathBuf, str::FromStr}; + +use crate::{db, subcommands::run_external, Lang, RecordOptions}; + +pub fn run_record(options: RecordOptions) { + println!("{:#?}", options); + + let lang = options.lang.or_else(|| detect_language(&options.program)); + if lang.is_none() { + panic!("Can't determine language"); // TODO: better error and what to do? + } + + let lang = lang.unwrap(); + let recorder_program = format!("codetracer-{}-recorder", lang.to_string()); + + run_external(&vec![recorder_program, options.program]); + + let db = db::CONNECTION_MUTEX.lock(); +} + +fn detect_language(program: &str) -> Option { + let path = match PathBuf::from_str(program) { + Ok(x) => x, + _ => return None, + }; + + if path.is_dir() { + if let Some(x) = detect_language_folder(&path) { + return Some(x); + } + } else { + if let Some(x) = detect_language_file(&path) { + return Some(x); + } + }; + + None +} + +fn detect_language_folder(path: &PathBuf) -> Option { + let nargo_path = path.join("Nargo.toml"); + + if nargo_path.is_file() { + Some(Lang::Noir) + } else { + None + } +} + +fn detect_language_file(path: &PathBuf) -> Option { + let extension = if let Some(ext_raw) = path.extension() + && let Some(ext) = ext_raw.to_str() + { + ext.to_string().to_lowercase() + } else { + return None; + }; + + match extension.as_str() { + "py" => Some(Lang::Python), + "rb" => Some(Lang::Ruby), + "nr" => Some(Lang::Noir), + "small" => Some(Lang::Small), + "wasm" => Some(Lang::Wasm), + _ => None, + } +} diff --git a/src/frontend/index/install.nim b/src/frontend/index/install.nim index 677600e7f..e5bd30338 100644 --- a/src/frontend/index/install.nim +++ b/src/frontend/index/install.nim @@ -102,7 +102,7 @@ proc isCtInstalled*(config: Config): bool = else: if not config.skipInstall: if process.platform == "darwin".toJs: - let ctLaunchersPath = cstring($paths.home / ".local" / "share" / "codetracer" / "shell-launchers" / "ct") + let ctLaunchersPath = cstring($paths.home / ".local" / "share" / "codetracer" / "shell-launchers" / "ct-legacy") return fs.existsSync(ctLaunchersPath) else: let dataHome = getEnv("XDG_DATA_HOME", getEnv("HOME") / ".local/share") diff --git a/src/frontend/ui/welcome_screen.nim b/src/frontend/ui/welcome_screen.nim index ae896e1aa..e3e69aabd 100644 --- a/src/frontend/ui/welcome_screen.nim +++ b/src/frontend/ui/welcome_screen.nim @@ -2,7 +2,7 @@ import std/[ options, jsffi, enumerate ], ui_imports, ../[ types ], - ../../ct/version + ../../common/version import std/times except now const @@ -682,7 +682,7 @@ proc loadInitialOptions(self: WelcomeScreenComponent) = WelcomeScreenOption( name: "Open online trace", inactive: false, - command: proc = + command: proc = self.openOnlineTrace = true self.welcomeScreen = false self.newDownload = NewDownloadRecord( diff --git a/src/shell-integrations/shell-launchers/ct b/src/shell-integrations/shell-launchers/ct-legacy similarity index 95% rename from src/shell-integrations/shell-launchers/ct rename to src/shell-integrations/shell-launchers/ct-legacy index 23450c917..b8d95ed02 100644 --- a/src/shell-integrations/shell-launchers/ct +++ b/src/shell-integrations/shell-launchers/ct-legacy @@ -10,7 +10,7 @@ if [[ -s ~/.local/share/codetracer/app-install-fs-location ]]; then if [[ $1 == "" || $1 == "run" ]]; then open "$app_location" --args "$@" else - "$app_location/Contents/MacOS/bin/ct" "$@" + "$app_location/Contents/MacOS/bin/ct-legacy" "$@" fi elif [ -f "$app_location" ]; then # The app binary has been linked directry. This is used sometimes during development. diff --git a/tsc-ui-tests/lib/ct_helpers.ts b/tsc-ui-tests/lib/ct_helpers.ts index 5873437e3..819063e6f 100644 --- a/tsc-ui-tests/lib/ct_helpers.ts +++ b/tsc-ui-tests/lib/ct_helpers.ts @@ -35,7 +35,7 @@ export const codetracerPath = // eslint-disable-next-line @typescript-eslint/no-magic-numbers envCodetracerPath.length > 0 ? envCodetracerPath - : path.join(linksPath, "bin", "ct"); + : path.join(linksPath, "bin", "ct-legacy"); const OK_EXIT_CODE = 0; const ERROR_EXIT_CODE = 1; @@ -113,7 +113,7 @@ export function wait(ms: number): Promise { function setupLdLibraryPath(): void { // originally in src/tester/tester.nim // required so /codetracer can be called internally - // (it is called from ct itself) + // (it is called from ct-legacy itself) // we need the correct ld library paths // for more info, please read the comment for `setupLdLibraryPath` // in src/tester/tester.nim; @@ -293,7 +293,7 @@ function recordTestProgram(recordArg: string): number { const lines = ctProcess.stdout.trim().split("\n"); const lastLine = lines[lines.length - 1]; // eslint-disable-line @typescript-eslint/no-magic-numbers if (!lastLine.startsWith("traceId:")) { - console.log("ERROR: unexpected last line of ct record:"); + console.log("ERROR: unexpected last line of ct-legacy record:"); console.log(lastLine); process.exit(ERROR_EXIT_CODE); } @@ -334,7 +334,7 @@ async function recordAndReplayTestProgram( const outputBinary = `${name}_${langExtension}`; const outputBinaryPath = path.join(testBinariesPath, outputBinary); - // uses ct record ; + // uses ct-legacy record ; // stores it in the shared central local db as all the normal records // maybe by an user, not in a separate test one! const traceId = buildAndRecordTestProgram(sourcePath, outputBinaryPath); diff --git a/ui-tests/Helpers/CodetracerLauncher.cs b/ui-tests/Helpers/CodetracerLauncher.cs index 6e6a971a8..f55d48a28 100644 --- a/ui-tests/Helpers/CodetracerLauncher.cs +++ b/ui-tests/Helpers/CodetracerLauncher.cs @@ -20,7 +20,7 @@ internal static class CodetracerLauncher Path.Combine( Environment.GetEnvironmentVariable("NIX_CODETRACER_EXE_DIR") ?? Path.Combine(RepoRoot, "src", "build-debug"), - "bin", "ct"); + "bin", "ct-legacy"); public static string CtInstallDir { get; } = Path.GetDirectoryName(CtPath)!; @@ -60,4 +60,3 @@ public static void StartCore(int traceId, int runPid) Thread.Sleep(5000); } } - diff --git a/ui-tests/Helpers/PlayrwightLauncher.cs b/ui-tests/Helpers/PlayrwightLauncher.cs index ca24a9e66..b23f415a1 100644 --- a/ui-tests/Helpers/PlayrwightLauncher.cs +++ b/ui-tests/Helpers/PlayrwightLauncher.cs @@ -35,7 +35,7 @@ private static async Task WaitForCdpAsync(int port, TimeSpan timeout) public static async Task LaunchAsync(string programRelativePath) { if (!IsCtAvailable) - throw new FileNotFoundException($"ct executable not found at {CtPath}"); + throw new FileNotFoundException($"ct-legacy executable not found at {CtPath}"); int traceId = CodetracerLauncher.RecordProgram(programRelativePath); int port = await GetFreeTcpPortAsync(); @@ -103,4 +103,4 @@ public static async Task GetAppPageAsync(IBrowser browser, string? titleC throw new TimeoutException("Could not find app page (non-DevTools) after connecting playwright."); } } -} \ No newline at end of file +} diff --git a/ui-tests/Helpers/SeleniumLauncher.cs b/ui-tests/Helpers/SeleniumLauncher.cs index 88e641eb8..1eea8f551 100644 --- a/ui-tests/Helpers/SeleniumLauncher.cs +++ b/ui-tests/Helpers/SeleniumLauncher.cs @@ -8,7 +8,7 @@ public static class SeleniumLauncher public static IWebDriver Launch(string programRelativePath) { if (!CodetracerLauncher.IsCtAvailable) - throw new FileNotFoundException($"ct executable not found at {CodetracerLauncher.CtPath}"); + throw new FileNotFoundException($"ct-legacy executable not found at {CodetracerLauncher.CtPath}"); int traceId = CodetracerLauncher.RecordProgram(programRelativePath); // CodetracerLauncher.StartCore(traceId, 1); @@ -33,4 +33,4 @@ public static IWebDriver Launch(string programRelativePath) return new ChromeDriver(driverDir, options); } -} \ No newline at end of file +} diff --git a/ui-tests/Tests/TestRunner.cs b/ui-tests/Tests/TestRunner.cs index d115b27e0..c8cd05dee 100644 --- a/ui-tests/Tests/TestRunner.cs +++ b/ui-tests/Tests/TestRunner.cs @@ -15,7 +15,7 @@ public static async Task RunAsync() { if (!PlaywrightLauncher.IsCtAvailable) { - Console.WriteLine($"ct executable not found at {PlaywrightLauncher.CtPath}. Build CodeTracer or set CODETRACER_E2E_CT_PATH."); + Console.WriteLine($"ct-legacy executable not found at {PlaywrightLauncher.CtPath}. Build CodeTracer or set CODETRACER_E2E_CT_PATH."); return; }