diff --git a/scripts/install.sh b/scripts/install.sh index bf4ba2d..967b1b8 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,6 +1,7 @@ -#!/usr/bin/env bash -# OWILIX Installer -# Usage: curl -fsSL https://opencode.it4i.eu/openwebsearcheu-public/owi-cli/-/raw/main/scripts/install.sh\?ref_type\=heads | sh +#!/bin/sh +# OWILIX Installer (POSIX sh) +# Usage: +# curl -fsSL https://opencode.it4i.eu/openwebsearcheu-public/owi-cli/-/raw/main/scripts/install.sh?ref_type=heads | sh # # Options (via environment variables): # OWILIX_VERSION - Specific version to install (default: latest) @@ -8,429 +9,474 @@ # OWILIX_NO_PATH - Set to 1 to skip PATH modification # OWILIX_UPGRADE - Set to 1 for upgrade mode # OWILIX_PM - Force package manager: uv, conda, mamba, pipx (skip selection) -# -set -euo pipefail - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -# Configuration -OWILIX_VERSION="${OWILIX_VERSION:-}" -OWILIX_PATH="${OWILIX_PATH:-$HOME/.venv/owilix}" -OWILIX_NO_PATH="${OWILIX_NO_PATH:-0}" -OWILIX_UPGRADE="${OWILIX_UPGRADE:-0}" -OWILIX_PM="${OWILIX_PM:-}" + +set -eu + +# ---- Colors (safe-ish for sh) ---- +RED=$(printf '\033[0;31m') +GREEN=$(printf '\033[0;32m') +YELLOW=$(printf '\033[1;33m') +BLUE=$(printf '\033[0;34m') +CYAN=$(printf '\033[0;36m') +NC=$(printf '\033[0m') + +log() { printf "%s[owilix]%s %s\n" "$BLUE" "$NC" "$1"; } +success() { printf "%s[owilix]%s %s\n" "$GREEN" "$NC" "$1"; } +warn() { printf "%s[owilix]%s %s\n" "$YELLOW" "$NC" "$1"; } +error() { printf "%s[owilix]%s %s\n" "$RED" "$NC" "$1" >&2; } + +# ---- Config ---- +OWILIX_VERSION=${OWILIX_VERSION:-} +OWILIX_PATH=${OWILIX_PATH:-"$HOME/.venv/owilix"} +OWILIX_NO_PATH=${OWILIX_NO_PATH:-0} +OWILIX_UPGRADE=${OWILIX_UPGRADE:-0} +OWILIX_PM=${OWILIX_PM:-} + OWILIX_INDEX="https://opencode.it4i.eu/api/v4/projects/92/packages/pypi/simple" PY4LEXIS_INDEX="https://opencode.it4i.eu/api/v4/projects/107/packages/pypi/simple" # Git dependency (not on PyPI) GIT_DEP="python-http-irods-client @ git+https://opencode.it4i.eu/lexis-platform/data/python-http-irods-client.git@1.1.1" -log() { echo -e "${BLUE}[owilix]${NC} $1"; } -success() { echo -e "${GREEN}[owilix]${NC} $1"; } -warn() { echo -e "${YELLOW}[owilix]${NC} $1"; } -error() { echo -e "${RED}[owilix]${NC} $1" >&2; } +# ---- Helpers ---- +have() { command -v "$1" >/dev/null 2>&1; } -# Detect OS detect_os() { - case "$(uname -s)" in - Linux*) OS="linux" ;; - Darwin*) OS="macos" ;; - MINGW*|CYGWIN*|MSYS*) OS="windows" ;; - *) OS="unknown" ;; - esac - log "Detected OS: $OS" + case "$(uname -s 2>/dev/null || echo unknown)" in + Linux*) OS="linux" ;; + Darwin*) OS="macos" ;; + MINGW*|CYGWIN*|MSYS*) OS="windows" ;; + *) OS="unknown" ;; + esac + log "Detected OS: $OS" } -# Detect available package managers detect_package_managers() { - AVAILABLE_PMS=() - - if command -v uv &>/dev/null; then - AVAILABLE_PMS+=("uv") - fi - if command -v conda &>/dev/null; then - AVAILABLE_PMS+=("conda") - fi - if command -v mamba &>/dev/null; then - AVAILABLE_PMS+=("mamba") - fi - if command -v pipx &>/dev/null; then - AVAILABLE_PMS+=("pipx") - fi - - log "Available package managers: ${AVAILABLE_PMS[*]:-none}" + AVAILABLE_PMS="" + have uv && AVAILABLE_PMS="$AVAILABLE_PMS uv" + have conda && AVAILABLE_PMS="$AVAILABLE_PMS conda" + have mamba && AVAILABLE_PMS="$AVAILABLE_PMS mamba" + have pipx && AVAILABLE_PMS="$AVAILABLE_PMS pipx" + + if [ -n "$AVAILABLE_PMS" ]; then + log "Available package managers:${AVAILABLE_PMS}" + else + log "Available package managers: none" + fi } -# Let user choose package manager -choose_package_manager() { - # If forced via env var, use that - if [[ -n "$OWILIX_PM" ]]; then - PM="$OWILIX_PM" - log "Using package manager (from OWILIX_PM): $PM" - return - fi - - # If only one available, use it - if [[ ${#AVAILABLE_PMS[@]} -eq 1 ]]; then - PM="${AVAILABLE_PMS[0]}" - log "Using package manager: $PM" - return - fi - - # If none available, install uv - if [[ ${#AVAILABLE_PMS[@]} -eq 0 ]]; then - log "No package managers found. Installing uv..." - install_uv - PM="uv" - return - fi - - # Multiple available - let user choose - echo - echo -e "${CYAN}Multiple package managers detected. Please choose:${NC}" - echo - - local i=1 - for pm in "${AVAILABLE_PMS[@]}"; do - case "$pm" in - uv) echo " $i) uv - Fast, recommended (creates venv at $OWILIX_PATH)" ;; - conda) echo " $i) conda - Creates 'owilix' conda environment" ;; - mamba) echo " $i) mamba - Fast conda alternative (creates 'owilix' env)" ;; - pipx) echo " $i) pipx - Isolated install (creates venv at $OWILIX_PATH)" ;; - esac - ((i++)) - done - echo - - read -p "Enter choice [1-${#AVAILABLE_PMS[@]}] (default: 1): " choice < /dev/tty - choice="${choice:-1}" - - if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#AVAILABLE_PMS[@]} )); then - PM="${AVAILABLE_PMS[$((choice-1))]}" - else - PM="${AVAILABLE_PMS[0]}" +count_words() { + # prints number of words in $1 + # shellcheck disable=SC2086 + set -- $1 + echo $# +} + +nth_word() { + # nth_word "a b c" 2 -> b + list=$1 + n=$2 + i=1 + for w in $list; do + if [ "$i" -eq "$n" ]; then + echo "$w" + return 0 fi - - log "Selected package manager: $PM" + i=$((i + 1)) + done + return 1 } -# Install uv if not present install_uv() { - if command -v uv &>/dev/null; then - log "uv is already installed: $(uv --version)" - return 0 - fi - - log "Installing uv..." - if command -v curl &>/dev/null; then - curl -fsSL https://astral.sh/uv/install.sh | sh - elif command -v wget &>/dev/null; then - wget -qO- https://astral.sh/uv/install.sh | sh - else - error "Neither curl nor wget found. Please install one first." - exit 1 - fi - - export PATH="$HOME/.local/bin:$PATH" - - if command -v uv &>/dev/null; then - success "uv installed: $(uv --version)" - AVAILABLE_PMS+=("uv") - else - error "Failed to install uv" - exit 1 - fi + if have uv; then + log "uv is already installed: $(uv --version 2>/dev/null || echo unknown)" + return 0 + fi + + log "Installing uv..." + if have curl; then + curl -fsSL https://astral.sh/uv/install.sh | sh + elif have wget; then + wget -qO- https://astral.sh/uv/install.sh | sh + else + error "Neither curl nor wget found. Please install one first." + exit 1 + fi + + # Common install location for uv + PATH="$HOME/.local/bin:$PATH" + export PATH + + if have uv; then + success "uv installed: $(uv --version 2>/dev/null || echo unknown)" + AVAILABLE_PMS="$AVAILABLE_PMS uv" + else + error "Failed to install uv" + exit 1 + fi } -# Install with uv +choose_package_manager() { + if [ -n "$OWILIX_PM" ]; then + PM=$OWILIX_PM + log "Using package manager (from OWILIX_PM): $PM" + return 0 + fi + + n=$(count_words "$AVAILABLE_PMS") + + if [ "$n" -eq 1 ]; then + PM=$(nth_word "$AVAILABLE_PMS" 1) + log "Using package manager: $PM" + return 0 + fi + + if [ "$n" -eq 0 ]; then + log "No package managers found. Installing uv..." + install_uv + PM="uv" + return 0 + fi + + echo "" + printf "%sMultiple package managers detected. Please choose:%s\n\n" "$CYAN" "$NC" + + i=1 + for pm in $AVAILABLE_PMS; do + case "$pm" in + uv) printf " %s) uv - Fast, recommended (creates venv at %s)\n" "$i" "$OWILIX_PATH" ;; + conda) printf " %s) conda - Creates 'owilix' conda environment\n" "$i" ;; + mamba) printf " %s) mamba - Fast conda alternative (creates 'owilix' env)\n" "$i" ;; + pipx) printf " %s) pipx - Isolated install (creates venv at %s)\n" "$i" "$OWILIX_PATH" ;; + esac + i=$((i + 1)) + done + echo "" + + # Read from tty so curl|sh still prompts + printf "Enter choice [1-%s] (default: 1): " "$n" > /dev/tty + choice=$(cat < /dev/tty || true) + [ -z "${choice:-}" ] && choice=1 + + case "$choice" in + *[!0-9]*|'') choice=1 ;; + esac + if [ "$choice" -lt 1 ] || [ "$choice" -gt "$n" ]; then + choice=1 + fi + + PM=$(nth_word "$AVAILABLE_PMS" "$choice" || true) + [ -z "${PM:-}" ] && PM=$(nth_word "$AVAILABLE_PMS" 1) + + log "Selected package manager: $PM" +} + +handle_existing_path() { + if [ -d "$OWILIX_PATH" ]; then + warn "Installation directory exists: $OWILIX_PATH" + printf "Remove and reinstall? [y/N] " > /dev/tty + reply=$(cat < /dev/tty || true) + case "$reply" in + y|Y) rm -rf "$OWILIX_PATH" ;; + *) error "Installation aborted"; exit 1 ;; + esac + fi +} + +# ---- Installers ---- install_with_uv() { - local version_arg="" - [[ -n "$OWILIX_VERSION" ]] && version_arg="==$OWILIX_VERSION" - - if [[ "$OWILIX_UPGRADE" == "1" ]] && [[ -d "$OWILIX_PATH" ]]; then - log "Upgrading with uv..." - source "$OWILIX_PATH/bin/activate" 2>/dev/null || true - uv pip install --upgrade "$GIT_DEP" "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" - else - handle_existing_path - - log "Creating virtual environment at $OWILIX_PATH..." - uv venv --python 3.11 "$OWILIX_PATH" - - log "Installing owilix with uv..." - source "$OWILIX_PATH/bin/activate" - uv pip install "$GIT_DEP" "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" - fi + version_arg="" + [ -n "$OWILIX_VERSION" ] && version_arg="==$OWILIX_VERSION" + + if [ "$OWILIX_UPGRADE" = "1" ] && [ -d "$OWILIX_PATH" ]; then + log "Upgrading with uv..." + # shellcheck disable=SC1090 + [ -f "$OWILIX_PATH/bin/activate" ] && . "$OWILIX_PATH/bin/activate" || true + uv pip install --upgrade "$GIT_DEP" "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" + return 0 + fi + + handle_existing_path + + log "Creating virtual environment at $OWILIX_PATH..." + uv venv --python 3.11 "$OWILIX_PATH" + + log "Installing owilix with uv..." + # shellcheck disable=SC1090 + . "$OWILIX_PATH/bin/activate" + uv pip install "$GIT_DEP" "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" +} + +conda_hook() { + # Make conda activate work in non-interactive sh + if have conda; then + # Prefer posix hook, fall back to sh hook + eval "$(conda shell.posix hook 2>/dev/null || conda shell.sh hook 2>/dev/null)" || true + fi } -# Install with conda install_with_conda() { - local version_arg="" - [[ -n "$OWILIX_VERSION" ]] && version_arg="==$OWILIX_VERSION" - - local env_name="owilix" - - if [[ "$OWILIX_UPGRADE" == "1" ]]; then - log "Upgrading with conda..." - conda activate "$env_name" 2>/dev/null || true - pip install --upgrade "$GIT_DEP" - pip install --upgrade "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" - else - if conda env list | grep -q "^$env_name "; then - warn "Conda environment '$env_name' exists" - read -p "Remove and recreate? [y/N] " -n 1 -r < /dev/tty - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - conda env remove -n "$env_name" -y - else - error "Installation aborted" - exit 1 - fi - fi - - log "Creating conda environment '$env_name'..." - conda create -n "$env_name" python=3.11 -y - - log "Installing owilix with conda/pip..." - eval "$(conda shell.bash hook)" - conda activate "$env_name" - pip install "$GIT_DEP" - pip install "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" + version_arg="" + [ -n "$OWILIX_VERSION" ] && version_arg="==$OWILIX_VERSION" + env_name="owilix" + + conda_hook + + if [ "$OWILIX_UPGRADE" = "1" ]; then + log "Upgrading with conda..." + conda activate "$env_name" >/dev/null 2>&1 || true + pip install --upgrade "$GIT_DEP" + pip install --upgrade "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" + else + if conda env list 2>/dev/null | grep -q "^$env_name[[:space:]]"; then + warn "Conda environment '$env_name' exists" + printf "Remove and recreate? [y/N] " > /dev/tty + reply=$(cat < /dev/tty || true) + case "$reply" in + y|Y) conda env remove -n "$env_name" -y ;; + *) error "Installation aborted"; exit 1 ;; + esac fi - - success "owilix installed in conda env '$env_name'" - warn "To use: conda activate $env_name" + + log "Creating conda environment '$env_name'..." + conda create -n "$env_name" python=3.11 -y + + log "Installing owilix with conda/pip..." + conda activate "$env_name" + pip install "$GIT_DEP" + pip install "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" + fi + + success "owilix installed in conda env '$env_name'" + warn "To use: conda activate $env_name" } -# Install with mamba install_with_mamba() { - local version_arg="" - [[ -n "$OWILIX_VERSION" ]] && version_arg="==$OWILIX_VERSION" - - local env_name="owilix" - - if [[ "$OWILIX_UPGRADE" == "1" ]]; then - log "Upgrading with mamba..." - mamba activate "$env_name" 2>/dev/null || conda activate "$env_name" || true - pip install --upgrade "$GIT_DEP" - pip install --upgrade "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" - else - if mamba env list 2>/dev/null | grep -q "^$env_name " || conda env list | grep -q "^$env_name "; then - warn "Mamba/conda environment '$env_name' exists" - read -p "Remove and recreate? [y/N] " -n 1 -r < /dev/tty - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - mamba env remove -n "$env_name" -y 2>/dev/null || conda env remove -n "$env_name" -y - else - error "Installation aborted" - exit 1 - fi - fi - - log "Creating mamba environment '$env_name'..." - mamba create -n "$env_name" python=3.11 -y - - log "Installing owilix with mamba/pip..." - eval "$(conda shell.bash hook)" - conda activate "$env_name" - pip install "$GIT_DEP" - pip install "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --extra-index-url "$PY4LEXIS_INDEX" + version_arg="" + [ -n "$OWILIX_VERSION" ] && version_arg="==$OWILIX_VERSION" + env_name="owilix" + + conda_hook + + if [ "$OWILIX_UPGRADE" = "1" ]; then + log "Upgrading with mamba..." + # activation varies; try conda hook/activate + conda activate "$env_name" >/dev/null 2>&1 || true + pip install --upgrade "$GIT_DEP" + pip install --upgrade "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" + else + if (have mamba && mamba env list 2>/dev/null | grep -q "^$env_name[[:space:]]") \ + || (have conda && conda env list 2>/dev/null | grep -q "^$env_name[[:space:]]"); then + warn "Mamba/conda environment '$env_name' exists" + printf "Remove and recreate? [y/N] " > /dev/tty + reply=$(cat < /dev/tty || true) + case "$reply" in + y|Y) + (have mamba && mamba env remove -n "$env_name" -y >/dev/null 2>&1) || true + (have conda && conda env remove -n "$env_name" -y >/dev/null 2>&1) || true + ;; + *) error "Installation aborted"; exit 1 ;; + esac fi - - success "owilix installed in mamba env '$env_name'" - warn "To use: mamba activate $env_name (or conda activate $env_name)" + + log "Creating mamba environment '$env_name'..." + mamba create -n "$env_name" python=3.11 -y + + log "Installing owilix with mamba/pip..." + conda activate "$env_name" + pip install "$GIT_DEP" + pip install "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --extra-index-url "$PY4LEXIS_INDEX" + fi + + success "owilix installed in mamba env '$env_name'" + warn "To use: mamba activate $env_name (or conda activate $env_name)" } -# Install with pipx install_with_pipx() { - local version_arg="" - [[ -n "$OWILIX_VERSION" ]] && version_arg="==$OWILIX_VERSION" - - if [[ "$OWILIX_UPGRADE" == "1" ]]; then - log "Upgrading with pipx..." - pipx upgrade owilix || true + version_arg="" + [ -n "$OWILIX_VERSION" ] && version_arg="==$OWILIX_VERSION" + + if [ "$OWILIX_UPGRADE" = "1" ]; then + log "Upgrading with pipx..." + pipx upgrade owilix >/dev/null 2>&1 || true + else + log "Installing owilix with pipx..." + # pipx doesn't handle git deps well, try pipx and fall back to uv + if pipx install "owilix${version_arg}" \ + --index-url "$OWILIX_INDEX" \ + --pip-args="--extra-index-url=$PY4LEXIS_INDEX" >/dev/null 2>&1 + then + : else - log "Installing owilix with pipx..." - # pipx doesn't handle git deps well, use pip in the created venv - pipx install "owilix${version_arg}" \ - --index-url "$OWILIX_INDEX" \ - --pip-args="--extra-index-url=$PY4LEXIS_INDEX" 2>/dev/null || { - warn "pipx install failed (likely git dependency issue)" - log "Falling back to uv installation..." - install_uv - PM="uv" - install_with_uv - return - } + warn "pipx install failed (likely git dependency issue)" + log "Falling back to uv installation..." + install_uv + PM="uv" + install_with_uv + return 0 fi - - success "owilix installed with pipx" -} + fi -# Handle existing installation path -handle_existing_path() { - if [[ -d "$OWILIX_PATH" ]]; then - warn "Installation directory exists: $OWILIX_PATH" - read -p "Remove and reinstall? [y/N] " -n 1 -r < /dev/tty - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - rm -rf "$OWILIX_PATH" - else - error "Installation aborted" - exit 1 - fi - fi + success "owilix installed with pipx" } -# Add to PATH +# ---- PATH setup ---- setup_path() { - # Skip for conda/mamba (they use activation) - if [[ "$PM" == "conda" ]] || [[ "$PM" == "mamba" ]]; then - return 0 - fi - - if [[ "$OWILIX_NO_PATH" == "1" ]]; then - log "Skipping PATH modification (OWILIX_NO_PATH=1)" - return 0 - fi - - local path_line="export PATH=\"$OWILIX_PATH/bin:\$PATH\"" - local shell_rc="" - - if [[ -n "${ZSH_VERSION:-}" ]] || [[ "$SHELL" == *"zsh"* ]]; then - shell_rc="$HOME/.zshrc" - elif [[ -n "${BASH_VERSION:-}" ]] || [[ "$SHELL" == *"bash"* ]]; then - [[ "$OS" == "macos" ]] && shell_rc="$HOME/.bash_profile" || shell_rc="$HOME/.bashrc" - elif [[ -f "$HOME/.profile" ]]; then - shell_rc="$HOME/.profile" - fi - - if [[ -n "$shell_rc" ]]; then - if grep -q "owilix" "$shell_rc" 2>/dev/null; then - log "PATH already configured in $shell_rc" - else - echo "" >> "$shell_rc" - echo "# OWILIX CLI" >> "$shell_rc" - echo "$path_line" >> "$shell_rc" - success "Added owilix to PATH in $shell_rc" - fi + # Skip for conda/mamba (they use activation) + if [ "$PM" = "conda" ] || [ "$PM" = "mamba" ]; then + return 0 + fi + + if [ "$OWILIX_NO_PATH" = "1" ]; then + log "Skipping PATH modification (OWILIX_NO_PATH=1)" + return 0 + fi + + path_line="export PATH=\"$OWILIX_PATH/bin:\$PATH\"" + shell_rc="" + + # In sh we can't reliably know the user's interactive shell; best effort: + case "${SHELL:-}" in + *zsh*) shell_rc="$HOME/.zshrc" ;; + *bash*) + if [ "$OS" = "macos" ]; then + shell_rc="$HOME/.bash_profile" + else + shell_rc="$HOME/.bashrc" + fi + ;; + *) + # POSIX default + shell_rc="$HOME/.profile" + ;; + esac + + if [ -n "$shell_rc" ]; then + if [ -f "$shell_rc" ] && grep -qi "owilix" "$shell_rc" 2>/dev/null; then + log "PATH already configured in $shell_rc" + else + { + echo "" + echo "# OWILIX CLI" + echo "$path_line" + } >> "$shell_rc" + success "Added owilix to PATH in $shell_rc" fi + fi } -# Check and run config migration +# ---- Config migration ---- check_migration() { - local owilix_bin="" - - case "$PM" in - uv|pipx) owilix_bin="$OWILIX_PATH/bin/owilix" ;; - conda|mamba) owilix_bin="owilix" ;; # Assume activated - esac - - log "Checking configuration status..." - - if ! "$owilix_bin" config version &>/dev/null 2>&1; then - log "No existing configuration found" - return 0 - fi - - local version_output - version_output=$("$owilix_bin" config version 2>&1) || true - echo "$version_output" - - if echo "$version_output" | grep -qi "migration available\|upgrade\|outdated"; then - echo - read -p "Config migration available. Run migration now? [Y/n] " -n 1 -r < /dev/tty - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - log "Running migration (dry-run first)..." - "$owilix_bin" config migrate --dry-run || true - echo - read -p "Apply migration? [y/N] " -n 1 -r < /dev/tty - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - "$owilix_bin" config migrate - success "Migration completed" - fi - fi - fi + owilix_bin="" + case "$PM" in + uv|pipx) owilix_bin="$OWILIX_PATH/bin/owilix" ;; + conda|mamba) owilix_bin="owilix" ;; + *) owilix_bin="owilix" ;; + esac + + log "Checking configuration status..." + + if ! "$owilix_bin" config version >/dev/null 2>&1; then + log "No existing configuration found" + return 0 + fi + + version_output=$("$owilix_bin" config version 2>&1 || true) + echo "$version_output" + + echo "$version_output" | grep -qi "migration available\|upgrade\|outdated" || return 0 + + echo "" + printf "Config migration available. Run migration now? [Y/n] " > /dev/tty + reply=$(cat < /dev/tty || true) + case "$reply" in + n|N) return 0 ;; + esac + + log "Running migration (dry-run first)..." + "$owilix_bin" config migrate --dry-run >/dev/null 2>&1 || true + echo "" + printf "Apply migration? [y/N] " > /dev/tty + reply2=$(cat < /dev/tty || true) + case "$reply2" in + y|Y) + "$owilix_bin" config migrate + success "Migration completed" + ;; + esac } -# Print usage instructions print_usage() { - echo - success "╔════════════════════════════════════════════════════════════════╗" - success "║ OWILIX installed successfully! ║" - success "╚════════════════════════════════════════════════════════════════╝" - echo - - case "$PM" in - uv|pipx) - echo " To use (after restarting terminal):" - echo " owilix --help" - ;; - conda) - echo " To use:" - echo " conda activate owilix" - echo " owilix --help" - ;; - mamba) - echo " To use:" - echo " mamba activate owilix # or: conda activate owilix" - echo " owilix --help" - ;; - esac - - echo - echo " Quick start:" - echo " owilix remote doctor # Check connection" - echo " owilix remote ls all # List datasets" - echo - echo " Documentation:" - echo " https://openwebsearcheu-public.pages.it4i.eu/owi-cli/" - echo + echo "" + success "╔════════════════════════════════════════════════════════════════╗" + success "║ OWILIX installed successfully! ║" + success "╚════════════════════════════════════════════════════════════════╝" + echo "" + + case "$PM" in + uv|pipx) + echo " To use (after restarting terminal):" + echo " owilix --help" + ;; + conda) + echo " To use:" + echo " conda activate owilix" + echo " owilix --help" + ;; + mamba) + echo " To use:" + echo " mamba activate owilix # or: conda activate owilix" + echo " owilix --help" + ;; + esac + + echo "" + echo " Quick start:" + echo " owilix remote doctor # Check connection" + echo " owilix remote ls all # List datasets" + echo "" + echo " Documentation:" + echo " https://openwebsearcheu-public.pages.it4i.eu/owi-cli/" + echo "" } -# Main installation flow main() { - echo - log "╔════════════════════════════════════════════════════════════════╗" - log "║ OWILIX Installer ║" - log "╚════════════════════════════════════════════════════════════════╝" - echo - - detect_os - detect_package_managers - choose_package_manager - - case "$PM" in - uv) install_with_uv ;; - conda) install_with_conda ;; - mamba) install_with_mamba ;; - pipx) install_with_pipx ;; - *) error "Unknown package manager: $PM"; exit 1 ;; - esac - - setup_path - check_migration - print_usage + echo "" + log "╔════════════════════════════════════════════════════════════════╗" + log "║ OWILIX Installer (sh) ║" + log "╚════════════════════════════════════════════════════════════════╝" + echo "" + + detect_os + detect_package_managers + choose_package_manager + + case "$PM" in + uv) install_with_uv ;; + conda) install_with_conda ;; + mamba) install_with_mamba ;; + pipx) install_with_pipx ;; + *) + error "Unknown package manager: $PM" + exit 1 + ;; + esac + + setup_path + check_migration + print_usage } main "$@" diff --git a/tests/check_http2.py b/tests/scripts/check_http2.py similarity index 100% rename from tests/check_http2.py rename to tests/scripts/check_http2.py diff --git a/tests/owilix/cmd/subcmds/s3_benchmark.py b/tests/scripts/cmd/subcmds/s3_benchmark.py similarity index 100% rename from tests/owilix/cmd/subcmds/s3_benchmark.py rename to tests/scripts/cmd/subcmds/s3_benchmark.py diff --git a/tests/owilix/core/db/benchmark_async_executor.py b/tests/scripts/core/db/benchmark_async_executor.py similarity index 100% rename from tests/owilix/core/db/benchmark_async_executor.py rename to tests/scripts/core/db/benchmark_async_executor.py diff --git a/tests/owilix/core/db/benchmark_comprehensive.py b/tests/scripts/core/db/benchmark_comprehensive.py similarity index 100% rename from tests/owilix/core/db/benchmark_comprehensive.py rename to tests/scripts/core/db/benchmark_comprehensive.py diff --git a/tests/owilix/core/db/benchmark_executor.py b/tests/scripts/core/db/benchmark_executor.py similarity index 100% rename from tests/owilix/core/db/benchmark_executor.py rename to tests/scripts/core/db/benchmark_executor.py diff --git a/tests/owilix/core/db/benchmark_query.py b/tests/scripts/core/db/benchmark_query.py similarity index 100% rename from tests/owilix/core/db/benchmark_query.py rename to tests/scripts/core/db/benchmark_query.py diff --git a/tests/owilix/core/db/inspect_schema.py b/tests/scripts/core/db/inspect_schema.py similarity index 100% rename from tests/owilix/core/db/inspect_schema.py rename to tests/scripts/core/db/inspect_schema.py diff --git a/tests/owilix/core/fsspec/benchmark_async.py b/tests/scripts/core/fsspec/benchmark_async.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_async.py rename to tests/scripts/core/fsspec/benchmark_async.py diff --git a/tests/owilix/core/fsspec/benchmark_connection.py b/tests/scripts/core/fsspec/benchmark_connection.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_connection.py rename to tests/scripts/core/fsspec/benchmark_connection.py diff --git a/tests/owilix/core/fsspec/benchmark_core_fsspec.py b/tests/scripts/core/fsspec/benchmark_core_fsspec.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_core_fsspec.py rename to tests/scripts/core/fsspec/benchmark_core_fsspec.py diff --git a/tests/owilix/core/fsspec/benchmark_listing.py b/tests/scripts/core/fsspec/benchmark_listing.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_listing.py rename to tests/scripts/core/fsspec/benchmark_listing.py diff --git a/tests/owilix/core/fsspec/benchmark_listing_duckdb.py b/tests/scripts/core/fsspec/benchmark_listing_duckdb.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_listing_duckdb.py rename to tests/scripts/core/fsspec/benchmark_listing_duckdb.py diff --git a/tests/owilix/core/fsspec/benchmark_optimized.py b/tests/scripts/core/fsspec/benchmark_optimized.py similarity index 100% rename from tests/owilix/core/fsspec/benchmark_optimized.py rename to tests/scripts/core/fsspec/benchmark_optimized.py diff --git a/tests/owilix/core/fsspec/example_core_fsspec_usage.py b/tests/scripts/core/fsspec/example_core_fsspec_usage.py similarity index 100% rename from tests/owilix/core/fsspec/example_core_fsspec_usage.py rename to tests/scripts/core/fsspec/example_core_fsspec_usage.py diff --git a/tests/do_oa.py b/tests/scripts/do_oa.py similarity index 100% rename from tests/do_oa.py rename to tests/scripts/do_oa.py diff --git a/tests/ducklake_postgres_tst.py b/tests/scripts/ducklake_postgres_tst.py similarity index 100% rename from tests/ducklake_postgres_tst.py rename to tests/scripts/ducklake_postgres_tst.py diff --git a/tests/fetch_lexis_samples.py b/tests/scripts/fetch_lexis_samples.py similarity index 100% rename from tests/fetch_lexis_samples.py rename to tests/scripts/fetch_lexis_samples.py diff --git a/tests/irods_connection_openidauthurl.py b/tests/scripts/irods_connection_openidauthurl.py similarity index 100% rename from tests/irods_connection_openidauthurl.py rename to tests/scripts/irods_connection_openidauthurl.py diff --git a/tests/lexis_ddiv2.py b/tests/scripts/lexis_ddiv2.py similarity index 100% rename from tests/lexis_ddiv2.py rename to tests/scripts/lexis_ddiv2.py diff --git a/tests/lexis_test.py b/tests/scripts/lexis_test.py similarity index 100% rename from tests/lexis_test.py rename to tests/scripts/lexis_test.py diff --git a/tests/lexis_test2.py b/tests/scripts/lexis_test2.py similarity index 100% rename from tests/lexis_test2.py rename to tests/scripts/lexis_test2.py diff --git a/tests/owilix_project.py b/tests/scripts/owilix_project.py similarity index 100% rename from tests/owilix_project.py rename to tests/scripts/owilix_project.py diff --git a/tests/s3a_test.py b/tests/scripts/s3a_test.py similarity index 100% rename from tests/s3a_test.py rename to tests/scripts/s3a_test.py diff --git a/tests/small_tst_py4lexis.py b/tests/scripts/small_tst_py4lexis.py similarity index 100% rename from tests/small_tst_py4lexis.py rename to tests/scripts/small_tst_py4lexis.py