Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Release with new features and bugfixes:
* https://github.com/devonfw/IDEasy/issues/1227[#1227]: Added Setup instrcutions to the Windows installer
* https://github.com/devonfw/IDEasy/issues/2114[#2114]: Fix false "Cygwin is not supported" warning in Git Bash
* https://github.com/devonfw/IDEasy/issues/865[#865]: az not working on Mac
* https://github.com/devonfw/IDEasy/issues/1808[#1808]: Do not report a workspace when `icd` navigates to the project root

The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/46?closed=1[milestone 2026.07.001].

Expand Down
18 changes: 15 additions & 3 deletions cli/src/main/package/bin/ide.bat
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,26 @@ for /f "tokens=*" %%i in ('"ideasy %IDE_OPTIONS% env"') do (
ideasy %IDE_OPTIONS% env >nul

if %ERRORLEVEL% EQU 0 (
if "%~1" == "" (
echo IDE environment variables have been set for %IDE_HOME% in workspace %WORKSPACE%
)
if "%~1" == "" call :printIdeHomeMessage
)

call :echoUseBash
goto :eof

REM prints the "environment variables have been set" line. Only mention the workspace when the
REM current directory is actually inside one; at the project root no workspace is reported (see #1808)
:printIdeHomeMessage
setlocal enabledelayedexpansion
set "_IDE_CWD=!CD!"
if defined WORKSPACE_PATH if not "!_IDE_CWD:%WORKSPACE_PATH%=!" == "!_IDE_CWD!" (
endlocal
echo IDE environment variables have been set for %IDE_HOME% in workspace %WORKSPACE%
exit /b
)
endlocal
echo IDE environment variables have been set for %IDE_HOME%
exit /b

:handleCreateCd
if "%~1" == "" exit /b
if "%~1" == "create" goto :findCreateProject
Expand Down
6 changes: 5 additions & 1 deletion cli/src/main/package/functions
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ function ide() {
if [ $? = 0 ]; then
eval "${ide_env}"
if [ $# = 0 ] && [ -n "${IDE_HOME}" ]; then
echo "IDE environment variables have been set for ${IDE_HOME} in workspace ${WORKSPACE}"
if [ -n "${WORKSPACE_PATH}" ] && [ "${PWD#"${WORKSPACE_PATH}"}" != "${PWD}" ]; then
echo "IDE environment variables have been set for ${IDE_HOME} in workspace ${WORKSPACE}"
else
echo "IDE environment variables have been set for ${IDE_HOME}"
fi
fi
fi
if _ide_is_cygwin && [ "$#" != 0 ]; then
Expand Down
125 changes: 123 additions & 2 deletions cli/src/test/functions-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,46 @@ source "${SCRIPT_DIR}/all-tests-functions.sh"

STUB_DIR="$(mktemp -d)"
trap 'rm -rf "${STUB_DIR}"' EXIT
# minimal fake "ideasy" binary so sourcing the functions file has no side effects
# fake "ideasy" binary. For the "env" subcommand it derives IDE_HOME, WORKSPACE and WORKSPACE_PATH
# from the current directory just like the real binary would, so that the icd message tests below
# can observe the project-root vs workspace behavior. For anything else it is a no-op.
cat > "${STUB_DIR}/ideasy" <<'EOS'
#!/usr/bin/env bash
case "$*" in
*env*)
home=""
dir="${PWD}"
while [ -n "${dir}" ] && [ "${dir}" != "/" ]; do
if [ -d "${dir}/workspaces" ] && [ -d "${dir}/settings" ]; then
home="${dir}"
break
fi
dir="$(dirname "${dir}")"
done
if [ -n "${home}" ]; then
workspace="main"
relative="${PWD#"${home}/"}"
if [ "${relative}" != "${PWD}" ]; then
case "${relative}" in
workspaces/*)
workspace="${relative#workspaces/}"
workspace="${workspace%%/*}"
;;
esac
fi
echo "IDE_HOME=${home}"
echo "WORKSPACE=${workspace}"
echo "WORKSPACE_PATH=${home}/workspaces/${workspace}"
fi
;;
esac
exit 0
EOS
chmod +x "${STUB_DIR}/ideasy"
mkdir -p "${STUB_DIR}/root"
# fake IDEasy project so the stub above recognizes it as an IDE_HOME
mkdir -p "${STUB_DIR}/root/project/settings"
mkdir -p "${STUB_DIR}/root/project/workspaces/main"
mkdir -p "${STUB_DIR}/root/project/workspaces/foo"

total=0
failed=0
Expand Down Expand Up @@ -63,6 +96,94 @@ check() {
fi
}

# runIcd <initial IDE_HOME> <icd args...> : sources the functions file in a fresh shell, exports
# IDE_ROOT (and IDE_HOME if given) and prints the output of "icd <args>".
runIcd() {
local initial_home="$1"
shift
# strip any inherited IDEasy state (and BASH_ENV, which may re-initialize it) so the test is hermetic
FUNCTIONS_FILE="${FUNCTIONS_FILE}" STUB_DIR="${STUB_DIR}" INITIAL_HOME="${initial_home}" \
env -u IDE_HOME -u WORKSPACE -u WORKSPACE_PATH -u IDE_OPTIONS -u BASH_ENV \
bash --noprofile --norc -c '
export PATH="${STUB_DIR}:${PATH}"
export IDE_ROOT="${STUB_DIR}/root"
cygpath() { echo "${@: -1}"; }
# source from the (project-less) IDE_ROOT so the "ide" call at the end of the functions file
# does not pick up a surrounding IDEasy project, then set the desired state for the test.
cd "${IDE_ROOT}" || exit 1
source "${FUNCTIONS_FILE}" >/dev/null 2>&1
unset IDE_HOME WORKSPACE WORKSPACE_PATH
[ -n "${INITIAL_HOME}" ] && export IDE_HOME="${INITIAL_HOME}"
icd "$@" 2>&1
' _ "$@"
}

# checkIcdInWorkspace <description> <expected substring> <initial IDE_HOME> <icd args...>
checkIcdInWorkspace() {
local description="$1" expected="$2" initial_home="$3"
shift 3
total=$((total + 1))
local output
output="$(runIcd "${initial_home}" "$@")"
if echo "${output}" | grep -qF "${expected}"; then
doSuccess "PASSED: ${description}"
else
doError "FAILED: ${description} - expected to contain '${expected}' but was '${output}'"
failed=$((failed + 1))
fi
}

# checkIcdProjectRoot <description> <initial IDE_HOME> <icd args...> : asserts the message reports the
# project home without mentioning any workspace (see #1808).
checkIcdProjectRoot() {
local description="$1" initial_home="$2"
shift 2
total=$((total + 1))
local output
output="$(runIcd "${initial_home}" "$@")"
if echo "${output}" | grep -qF "have been set for" && ! echo "${output}" | grep -q "workspace"; then
doSuccess "PASSED: ${description}"
else
doError "FAILED: ${description} - expected a project-root message without any workspace but was '${output}'"
failed=$((failed + 1))
fi
}

# checkIcdNoSetup <description> <initial IDE_HOME> <icd args...> : asserts that no environment is set
# up and no "have been set" message is printed (icd only navigates to the projects root, see #1808).
checkIcdNoSetup() {
local description="$1" initial_home="$2"
shift 2
total=$((total + 1))
local output
output="$(runIcd "${initial_home}" "$@")"
if ! echo "${output}" | grep -q "have been set"; then
doSuccess "PASSED: ${description}"
else
doError "FAILED: ${description} - expected no environment setup message but was '${output}'"
failed=$((failed + 1))
fi
}

echo "Testing project-root vs workspace message via icd in ${FUNCTIONS_FILE}"

# icd -p navigates to the project root, so the message must not mention any workspace at all (see #1808)
checkIcdProjectRoot "icd -p project reports the project home without any workspace" \
"" -p project
# icd -p -w navigates into the (default main) workspace, so the established "in workspace <name>" wording is kept
checkIcdInWorkspace "icd -p project -w reports 'in workspace main'" \
"in workspace main" "" -p project -w
# icd -p -w <name> navigates into the named workspace
checkIcdInWorkspace "icd -p project -w foo reports 'in workspace foo'" \
"in workspace foo" "" -p project -w foo
# inside a project, bare icd jumps to IDE_HOME (the project root), so it must not mention any workspace
checkIcdProjectRoot "icd (no args, inside a project) reports the project home without any workspace" \
"${STUB_DIR}/root/project"
# outside any project, bare icd only navigates to IDE_ROOT (the projects root) without any env setup or message
checkIcdNoSetup "icd (no args, no project) navigates to the projects root without any setup message" \
""

echo
echo "Testing Cygwin warning detection in ${FUNCTIONS_FILE}"

# genuine Cygwin -> warning is intended
Expand Down
4 changes: 2 additions & 2 deletions documentation/cli.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ In case you are not inside of a `IDEasy` folder the command will echo a message
You are not inside an IDEasy installation: /
[~]$ cd projects/my-project/workspaces/test/my-git-repo
[my-git-repo]$ ide
IDEasy environment variables have been set for /projects/my-project in workspace main
IDEasy environment variables have been set for /projects/my-project in workspace test
[my-git-repo]$ echo $IDE_HOME
~/projects/my-project
[my-git-repo]$ echo $JAVA_HOME
Expand Down Expand Up @@ -129,6 +129,6 @@ IDE environment variables have been set for /~/projects/myproject in workspace m
[~/projects/myproject/workspaces/myworkspace]$ cd myrepo/mymodule/src/main/java/com/foo/bar/some/path
[.../some/path]$ echo "do something here but now I want to go back to my project root dir"
[.../some/path]$ icd
IDE environment variables have been set for /~/projects/myproject in workspace main
IDE environment variables have been set for /~/projects/myproject
[~/projects/myproject]$ echo "Wow! IDEasy is awesome!"
```
2 changes: 1 addition & 1 deletion documentation/features.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Here are some examples with `IDEasy`:
[cool-project]$ mvn
command not found: mvn
[cool-project]$ ide
Environment variables have been set for ~/projects/cool-project in workspace main
Environment variables have been set for ~/projects/cool-project
[devonfw]$ mvn -v
Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: ~/projects/cool-project/software/mvn
Expand Down
Loading