Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(install): ensure home dir expansion works as expected #88

Merged
merged 2 commits into from
Jan 27, 2025
Merged
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ contributoor update # Update to latest version
contributoor logs # Show logs
```

If you chose to install contributoor under a custom directory, you will need to specify the directory when running the commands, for example:

```bash
contributoor --config-path /path/to/contributoor start
```

## 🔨 Development

<details>
Expand Down
100 changes: 91 additions & 9 deletions install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,11 @@ EOF
*) return 0 ;;
esac
}
export -f detect_platform sudo docker
function contributoor() {
echo "Config Path : $TEST_DIR/.contributoor/config.yaml"
return 0
}
export -f detect_platform sudo docker contributoor
export HOME="$TEST_DIR"

# Test 'no' response
Expand Down Expand Up @@ -1064,9 +1068,14 @@ EOF
case "$2" in
"systemctl") return 0 ;;
"docker") return 0 ;;
"contributoor") return 0 ;;
*) command "$@" ;;
esac
}
contributoor() {
echo "Config Path : $TEST_DIR/.contributoor/config.yaml"
return 0
}
sudo() {
case "$1" in
"systemctl")
Expand Down Expand Up @@ -1098,7 +1107,7 @@ EOF
*) return 0 ;;
esac
}
export -f detect_platform command sudo docker
export -f detect_platform command sudo docker contributoor

printf "y\n" | uninstall
'
Expand Down Expand Up @@ -1134,6 +1143,16 @@ EOF

# Setup mock functions
detect_platform() { echo "darwin"; }
command() {
case "$2" in
"contributoor") return 0 ;;
*) return 1 ;;
esac
}
contributoor() {
echo "Config Path : $TEST_DIR/.contributoor/config.yaml"
return 0
}
sudo() {
case "$1" in
"launchctl")
Expand All @@ -1153,7 +1172,7 @@ EOF
;;
esac
}
export -f detect_platform sudo
export -f detect_platform command sudo contributoor

printf "y\n" | uninstall
'
Expand All @@ -1165,32 +1184,95 @@ EOF
}

@test "uninstall handles missing components gracefully" {
# Create minimal test environment.
mkdir -p "$TEST_DIR"
# Create minimal test environment with config path
mkdir -p "$TEST_DIR/.contributoor"
touch "$TEST_DIR/.contributoor/config.yaml"

# Setup mock functions.
# Setup mock functions
function detect_platform() { echo "linux"; }
function command() {
case "$2" in
"systemctl") return 1 ;; # systemd not available
"docker") return 1 ;; # docker not available
"contributoor") return 0 ;;
*) command "$@" ;;
esac
}
function contributoor() {
echo "Config Path : $TEST_DIR/.contributoor/config.yaml"
return 0
}
function sudo() {
"${@:2}"
return 0
}
export -f detect_platform command sudo
export -f detect_platform command sudo contributoor
export HOME="$TEST_DIR"

# Run uninstall with 'yes' response.
# Run uninstall with 'yes' response
run bash -c '
source ./install.sh
printf "y\n" | uninstall
'

# Should complete successfully even with nothing to clean.
# Should complete successfully even with nothing to clean
[ "$status" -eq 0 ]
echo "$output" | grep -q "Contributoor has been uninstalled successfully"
}

@test "installation path expands tilde correctly" {
# Setup test environment
export HOME="$TEST_DIR"
CUSTOM_PATH="~/custom/contributoor"
EXPECTED_PATH="$TEST_DIR/custom/contributoor"

run bash -c "
source ./install.sh
CUSTOM_PATH='$CUSTOM_PATH'
# Expand ~ to \$HOME in a portable way
CUSTOM_PATH=\$(echo \"\$CUSTOM_PATH\" | sed \"s|^~|\$HOME|\")
echo \$CUSTOM_PATH
"

[ "$status" -eq 0 ]
[ "$output" = "$EXPECTED_PATH" ]
}

@test "uninstall handles tilde expansion in config path" {
# Create test environment with config in custom path
CUSTOM_DIR="$TEST_DIR/custom/contributoor"
mkdir -p "$CUSTOM_DIR"
touch "$CUSTOM_DIR/config.yaml"
export HOME="$TEST_DIR"

# Run uninstall with config path using tilde
run bash -c '
source ./install.sh
CONFIG_PATH="~/custom/contributoor/config.yaml"
detect_platform() { echo "linux"; }
command() { return 1; }
export -f detect_platform command
printf "y\n" | CONFIG_PATH="$CONFIG_PATH" uninstall
'

# Should expand ~ and find the config
[ "$status" -eq 0 ]
echo "$output" | grep -q "custom/contributoor"
[ ! -d "$CUSTOM_DIR" ]
}

@test "uninstall fails with non-existent config path after tilde expansion" {
export HOME="$TEST_DIR"

run bash -c '
source ./install.sh
CONFIG_PATH="~/nonexistent/config.yaml"
detect_platform() { echo "linux"; }
command() { return 1; }
export -f detect_platform command
printf "y\n" | CONFIG_PATH="$CONFIG_PATH" uninstall
'

[ "$status" -eq 1 ]
echo "$output" | grep -q "Config file not found at: $TEST_DIR/nonexistent/config.yaml"
}
56 changes: 47 additions & 9 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ warn() {
}

usage() {
echo "Usage: $0 [-p path] [-v version] [-u]"
echo "Usage: $0 [-p path] [-v version] [-u] [-c config_path]"
echo " -p: Path to install contributoor (default: $HOME/.contributoor)"
echo " -v: Version of contributoor to install without 'v' prefix (default: latest, example: 0.0.6)"
echo " -u: Uninstall Contributoor"
echo " -c: Path to config.yaml (only used with -u for uninstall)"
exit 1
}

Expand Down Expand Up @@ -599,11 +600,37 @@ EOF
}

uninstall() {
# Try to determine the installation directory
local install_dir=""

# If config path was provided via -c, use it
if [ -n "${CONFIG_PATH:-}" ]; then
# Expand ~ to $HOME in a portable way
CONFIG_PATH=$(echo "$CONFIG_PATH" | sed "s|^~|$HOME|")
if [ ! -f "$CONFIG_PATH" ]; then
fail "Config file not found at: $CONFIG_PATH"
fi
install_dir=$(dirname "$CONFIG_PATH")
else
# Try using contributoor status
if command -v contributoor >/dev/null 2>&1; then
local config_path=$(contributoor status 2>/dev/null | grep "Config Path" | cut -d':' -f2 | tr -d ' ')
if [ -n "$config_path" ]; then
install_dir=$(dirname "$config_path")
fi
fi

# If we couldn't determine the install directory, ask user to specify.
if [ -z "$install_dir" ]; then
fail "Could not determine installation directory.\nIt's likely you installed contributoor under a custom directory.\n\nPlease specify the directory when running the uninstaller:\n./install.sh -u -c /path/to/custom/config.yaml"
fi
fi

printf "\n${COLOR_RED}Warning, this will:${COLOR_RESET}\n"
printf " • Stop and remove any contributoor services (systemd/launchd)\n"
printf " • Stop and remove any contributoor Docker containers and images\n"
printf " • Remove contributoor from your PATH\n"
printf " • Delete all contributoor data from ${HOME}/.contributoor\n\n"
printf " • Delete all contributoor data from ${install_dir}\n\n"
printf "Are you sure you want to uninstall? [y/N]: "
read -r confirm
case "$(echo "$confirm" | tr '[:upper:]' '[:lower:]')" in
Expand Down Expand Up @@ -663,19 +690,20 @@ uninstall() {
fi

# Remove PATH entry from shell config
local bin_path="$install_dir/bin"
for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile" "$HOME/.profile"; do
if [ -f "$rc" ]; then
temp_file=$(mktemp)
grep -v "export PATH=.*contributoor.*bin" "$rc" > "$temp_file"
grep -v "export PATH=.*$bin_path" "$rc" > "$temp_file"
mv "$temp_file" "$rc"
success "Cleaned PATH from $rc"
fi
done

# Remove contributoor directory
if [ -d "$HOME/.contributoor" ]; then
rm -rf "$HOME/.contributoor"
success "Removed contributoor directory"
# Remove contributoor directory using detected path
if [ -d "$install_dir" ]; then
rm -rf "$install_dir"
success "Removed contributoor directory: $install_dir"
fi

printf "\n\n${COLOR_GREEN}Contributoor has been uninstalled successfully${COLOR_RESET}\n\n"
Expand All @@ -684,16 +712,24 @@ uninstall() {

main() {
# Parse arguments
while getopts "p:v:hu" FLAG; do
SHOULD_UNINSTALL=false
while getopts "p:v:c:hu" FLAG; do
case "$FLAG" in
p) CONTRIBUTOOR_PATH="$OPTARG" ;;
v) CONTRIBUTOOR_VERSION="$OPTARG" ;;
u) uninstall ;;
c) CONFIG_PATH="$OPTARG" ;;
u) SHOULD_UNINSTALL=true ;;
h) usage ;;
*) usage ;;
esac
done

# Handle uninstall if requested
if [ "$SHOULD_UNINSTALL" = true ]; then
uninstall
exit 0
fi

# Setup environment
CONTRIBUTOOR_BIN="$CONTRIBUTOOR_PATH/bin"
ARCH=$(detect_architecture)
Expand Down Expand Up @@ -726,6 +762,8 @@ main() {
read -r CUSTOM_PATH
fi
if [ -n "$CUSTOM_PATH" ]; then
# Expand ~ to $HOME in a portable way
CUSTOM_PATH=$(echo "$CUSTOM_PATH" | sed "s|^~|$HOME|")
CONTRIBUTOOR_PATH="$CUSTOM_PATH"
CONTRIBUTOOR_BIN="$CONTRIBUTOOR_PATH/bin"
fi
Expand Down
Loading