Refactor the herolib repo:

- Removed the unused files
- Updated the README
- Added all needed scripts in /scripts dir
- Update script paths in CI configuration
- Update script paths in Go code
- Move installation scripts to scripts directory
- Change script path from ./install_v.sh to ./scripts/install_v.sh
This commit is contained in:
Mahmoud-Emad
2025-11-17 15:04:49 +02:00
parent 2ab0dfa6b8
commit 49868a18e1
445 changed files with 18 additions and 40974 deletions

580
scripts/install_v.sh Executable file
View File

@@ -0,0 +1,580 @@
#!/bin/bash
set -euo pipefail
#==============================================================================
# GLOBAL VARIABLES
#==============================================================================
RESET=false
REMOVE=false
INSTALL_ANALYZER=false
HEROLIB=false
START_REDIS=false
export DIR_BASE="$HOME"
export DIR_BUILD="/tmp"
export DIR_CODE="$DIR_BASE/code"
export DIR_CODE_V="$DIR_BASE/_code"
export OSNAME=""
#==============================================================================
# FUNCTION DEFINITIONS
#==============================================================================
# Help function
print_help() {
echo "V & HeroLib Installer Script"
echo
echo "Usage: $0 [options]"
echo
echo "Options:"
echo " -h, --help Show this help message"
echo " --reset Force reinstallation of V"
echo " --remove Remove V installation and exit"
echo " --analyzer Install/update v-analyzer"
echo " --herolib Install our herolib"
echo " --herolib-version=VERSION Install specific herolib tag/branch (default: development)"
echo " --start-redis Start the Redis service if installed"
echo
echo "Examples:"
echo " $0"
echo " $0 --reset "
echo " $0 --remove "
echo " $0 --analyzer "
echo " $0 --herolib "
echo " $0 --reset --analyzer # Fresh install of both"
echo
}
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to run commands with sudo if needed
function run_sudo() {
# Check if we're already root
if [ "$(id -u)" -eq 0 ]; then
# We are root, run the command directly
"$@"
# Check if sudo is installed
elif command_exists sudo; then
# Use sudo to run the command
sudo "$@"
else
# No sudo available, try to run directly
"$@"
fi
}
check_release() {
if ! command -v lsb_release >/dev/null 2>&1; then
echo "❌ lsb_release command not found. Install 'lsb-release' package first."
exit 1
fi
CODENAME=$(lsb_release -sc)
RELEASE=$(lsb_release -rs)
if dpkg --compare-versions "$RELEASE" lt "24.04"; then
echo " Detected Ubuntu $RELEASE ($CODENAME). Skipping mirror fix (requires 24.04+)."
return 1
fi
return 0
}
ubuntu_sources_fix() {
# Check if we're on Ubuntu
if [[ "${OSNAME}" != "ubuntu" ]]; then
echo " Not running on Ubuntu. Skipping mirror fix."
return 1
fi
if check_release; then
local CODENAME
CODENAME=$(lsb_release -sc)
local TIMESTAMP
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
echo "🔎 Fixing apt mirror setup for Ubuntu $(lsb_release -rs) ($CODENAME)..."
if [ -f /etc/apt/sources.list ]; then
echo "📦 Backing up /etc/apt/sources.list -> /etc/apt/sources.list.backup.$TIMESTAMP"
run_sudo mv /etc/apt/sources.list /etc/apt/sources.list.backup.$TIMESTAMP
fi
if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then
echo "📦 Backing up /etc/apt/sources.list.d/ubuntu.sources -> /etc/apt/sources.list.d/ubuntu.sources.backup.$TIMESTAMP"
run_sudo mv /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.backup.$TIMESTAMP
fi
echo "📝 Writing new /etc/apt/sources.list.d/ubuntu.sources"
run_sudo tee /etc/apt/sources.list.d/ubuntu.sources >/dev/null <<EOF
Types: deb
URIs: mirror://mirrors.ubuntu.com/mirrors.txt
Suites: $CODENAME $CODENAME-updates $CODENAME-backports $CODENAME-security
Components: main restricted universe multiverse
EOF
echo "🔄 Running apt update..."
run_sudo apt update -qq
echo "✅ Done! Your system now uses the rotating Ubuntu mirror list."
fi
}
function sshknownkeysadd {
mkdir -p ~/.ssh
touch ~/.ssh/known_hosts
if ! grep github.com ~/.ssh/known_hosts > /dev/null
then
ssh-keyscan github.com >> ~/.ssh/known_hosts
fi
if ! grep git.threefold.info ~/.ssh/known_hosts > /dev/null
then
ssh-keyscan git.threefold.info >> ~/.ssh/known_hosts
fi
git config --global pull.rebase false
}
# Performs a non-interactive, forceful apt installation.
# WARNING: This is designed for CI/automated environments. It can be dangerous
# on a personal machine as it may remove essential packages to resolve conflicts.
function apt_force_install {
run_sudo apt -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" install "$@" -q -y --allow-downgrades --allow-remove-essential
}
is_github_actions() {
# echo "Checking GitHub Actions environment..."
# echo "GITHUB_ACTIONS=${GITHUB_ACTIONS:-not set}"
if [ -n "${GITHUB_ACTIONS:-}" ] && [ "$GITHUB_ACTIONS" = "true" ]; then
echo "Running in GitHub Actions: true"
return 0
else
echo "Running in GitHub Actions: false"
return 1
fi
}
function myplatform {
if [[ "${OSTYPE}" == "darwin"* ]]; then
export OSNAME='darwin'
elif [ -e /etc/os-release ]; then
# Read the ID field from the /etc/os-release file
export OSNAME=$(grep '^ID=' /etc/os-release | cut -d= -f2)
if [ "${OSNAME,,}" == "ubuntu" ]; then
export OSNAME="ubuntu"
fi
if [ "${OSNAME}" == "archarm" ]; then
export OSNAME="arch"
fi
if [ "${OSNAME}" == "debian" ]; then
export OSNAME="ubuntu"
fi
else
echo "Unable to determine the operating system."
exit 1
fi
}
function update_system {
echo ' - System Update'
if [[ "${OSNAME}" == "ubuntu" ]]; then
ubuntu_sources_fix
if is_github_actions; then
echo "github actions: preparing system"
else
rm -f /var/lib/apt/lists/lock
rm -f /var/cache/apt/archives/lock
rm -f /var/lib/dpkg/lock*
fi
export TERM=xterm
export DEBIAN_FRONTEND=noninteractive
run_sudo dpkg --configure -a
run_sudo apt update -y
if is_github_actions; then
echo "** IN GITHUB ACTIONS, DON'T DO SYSTEM UPGRADE"
else
set +e
echo "** System Upgrade"
apt-mark hold grub-efi-amd64-signed
set -e
apt upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
apt autoremove -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
fi
elif [[ "${OSNAME}" == "darwin"* ]]; then
if ! command -v brew >/dev/null 2>&1; then
echo ' - Installing Homebrew'
export NONINTERACTIVE=1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
unset NONINTERACTIVE
fi
elif [[ "${OSNAME}" == "alpine"* ]]; then
apk update
elif [[ "${OSNAME}" == "arch"* ]]; then
pacman -Syyu --noconfirm
fi
echo ' - System Update Done'
}
function install_packages {
echo ' - Installing Packages'
if [[ "${OSNAME}" == "ubuntu" ]]; then
apt_force_install apt-transport-https ca-certificates curl wget software-properties-common tmux make gcc rclone rsync mc redis-server screen net-tools git dnsutils htop lsb-release binutils pkg-config libssl-dev iproute2
elif [[ "${OSNAME}" == "darwin"* ]]; then
# The set +e is to prevent script failure if some packages are already installed.
set +e
brew install mc redis curl tmux screen htop wget rclone tcc
set -e
elif [[ "${OSNAME}" == "alpine"* ]]; then
apk add --no-cache screen git htop tmux mc curl rsync redis bash bash-completion rclone
# Switch default shell to bash for better interactive use
sed -i 's#/bin/ash#/bin/bash#g' /etc/passwd
elif [[ "${OSNAME}" == "arch"* ]]; then
pacman -Su --noconfirm arch-install-scripts gcc mc git tmux curl htop redis wget screen net-tools sudo lsb-release rclone
# Check if builduser exists, create if not
if ! id -u builduser > /dev/null 2>&1; then
useradd -m builduser
echo "builduser:$(openssl rand -base64 32 | sha256sum | base64 | head -c 32)" | chpasswd
echo 'builduser ALL=(ALL) NOPASSWD: ALL' | tee /etc/sudoers.d/builduser
fi
fi
echo ' - Package Installation Done'
}
function hero_lib_pull {
pushd $DIR_CODE/github/incubaid/herolib 2>&1 >> /dev/null
if [[ $(git status -s) ]]; then
echo "There are uncommitted changes in the Git repository herolib."
return 1
fi
git pull
popd 2>&1 >> /dev/null
}
function hero_lib_get {
mkdir -p $DIR_CODE/github/incubaid
if [[ -d "$DIR_CODE/github/incubaid/herolib" ]]
then
hero_lib_pull
else
pushd $DIR_CODE/github/incubaid 2>&1 >> /dev/null
git clone --depth 1 --no-single-branch https://github.com/incubaid/herolib.git
popd 2>&1 >> /dev/null
fi
# Checkout specific version if requested
if [ -n "${HEROLIB_VERSION:-}" ]; then
pushd $DIR_CODE/github/incubaid/herolib 2>&1 >> /dev/null
if ! git checkout "$HEROLIB_VERSION"; then
echo "Failed to checkout herolib version: $HEROLIB_VERSION"
popd 2>&1 >> /dev/null
return 1
fi
popd 2>&1 >> /dev/null
fi
}
remove_all() {
echo "Removing V installation..."
# Set reset to true to use existing reset functionality
RESET=true
# Call reset functionality
run_sudo rm -rf ~/code/v
run_sudo rm -rf ~/_code/v
run_sudo rm -rf ~/.config/v-analyzer
if command_exists v; then
echo "Removing V from system..."
run_sudo rm -f $(which v)
fi
if command_exists v-analyzer; then
echo "Removing v-analyzer from system..."
run_sudo rm -f $(which v-analyzer)
fi
# Remove v-analyzer path from rc files
for RC_FILE in ~/.zshrc ~/.bashrc; do
if [ -f "$RC_FILE" ]; then
echo "Cleaning up $RC_FILE..."
# Create a temporary file
TMP_FILE=$(mktemp)
# Remove lines containing v-analyzer/bin path
sed '/v-analyzer\/bin/d' "$RC_FILE" > "$TMP_FILE"
# Remove empty lines at the end of file
sed -i.bak -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$TMP_FILE"
# Replace original file
mv "$TMP_FILE" "$RC_FILE"
echo "Cleaned up $RC_FILE"
fi
done
echo "V removal complete"
}
# Starts the Redis service if it is not already running.
function start_redis_service() {
echo "Attempting to start Redis service..."
# Check if redis-server is even installed
if ! command_exists redis-server; then
echo "Warning: redis-server command not found. Skipping."
return 0
fi
# Check if redis is already running by pinging it
if redis-cli ping > /dev/null 2>&1; then
echo "Redis is already running."
return 0
fi
echo "Redis is not running. Attempting to start it..."
if command_exists systemctl; then
run_sudo systemctl start redis
# For Alpine, use rc-service
elif command_exists rc-service; then
run_sudo rc-service redis start
elif [[ "${OSNAME}" == "darwin"* ]]; then
# For macOS, use brew services
if ! brew services list | grep -q "^redis.*started"; then
brew services start redis
fi
else
echo "No service manager found, starting Redis manually..."
redis-server --daemonize yes
return 1
fi
# Final check to see if it started
sleep 1 # Give it a second to start up
if redis-cli ping > /dev/null 2>&1; then
echo "Redis started successfully."
else
echo "Error: Failed to start Redis."
exit 1
fi
}
v-install() {
# Check if v is already installed and in PATH
if command_exists v; then
echo "V is already installed and in PATH."
# Optionally, verify the installation location or version if needed
# For now, just exit the function assuming it's okay
return 0
fi
# Only clone and install if directory doesn't exist
# Note: The original check was for ~/code/v, but the installation happens in ~/_code/v.
if [ ! -d ~/_code/v ]; then
echo "Cloning V..."
mkdir -p ~/_code
cd ~/_code
if ! git clone --depth=1 https://github.com/vlang/v; then
echo "❌ Failed to clone V. Cleaning up..."
rm -rf "$V_DIR"
exit 1
fi
fi
# Only clone and install if directory doesn't exist
# Note: The original check was for ~/code/v, but the installation happens in ~/_code/v.
# Adjusting the check to the actual installation directory.
echo "Building V..."
cd ~/_code/v
make
# Verify the build produced the executable
if [ ! -x ~/_code/v/v ]; then
echo "Error: V build failed, executable ~/_code/v/v not found or not executable."
exit 1
fi
# Check if the built executable can report its version
if ! ~/_code/v/v -version > /dev/null 2>&1; then
echo "Error: Built V executable (~/_code/v/v) failed to report version."
exit 1
fi
echo "V built successfully. Creating symlink..."
run_sudo ./v symlink
# Verify v is in path
if ! command_exists v; then
echo "Error: V installation failed or not in PATH"
echo "Please ensure ~/code/v is in your PATH"
exit 1
fi
echo "V installation successful!"
}
v-analyzer() {
set -ex
# Install v-analyzer if requested
if [ "$INSTALL_ANALYZER" = true ]; then
echo "Installing v-analyzer..."
cd /tmp
v download -RD https://raw.githubusercontent.com/vlang/v-analyzer/main/install.vsh
# Check if v-analyzer bin directory exists
if [ ! -d "$HOME/.config/v-analyzer/bin" ]; then
echo "Error: v-analyzer bin directory not found at $HOME/.config/v-analyzer/bin"
echo "Please ensure v-analyzer was installed correctly"
exit 1
fi
echo "v-analyzer installation successful!"
fi
# Add v-analyzer to PATH if installed
if [ -d "$HOME/.config/v-analyzer/bin" ]; then
V_ANALYZER_PATH='export PATH="$PATH:$HOME/.config/v-analyzer/bin"'
# Function to add path to rc file if not present
add_to_rc() {
local RC_FILE="$1"
if [ -f "$RC_FILE" ]; then
if ! grep -q "v-analyzer/bin" "$RC_FILE"; then
echo "" >> "$RC_FILE"
echo "$V_ANALYZER_PATH" >> "$RC_FILE"
echo "Added v-analyzer to $RC_FILE"
else
echo "v-analyzer path already exists in $RC_FILE"
fi
fi
}
# Add to both .zshrc and .bashrc if they exist
add_to_rc ~/.zshrc
if [ "$(uname)" = "Darwin" ] && [ -f ~/.bashrc ]; then
add_to_rc ~/.bashrc
fi
fi
}
#==============================================================================
# MAIN EXECUTION
#==============================================================================
main() {
# Make sure we're running in the directory where the script is
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Parse arguments
for arg in "$@"; do
case $arg in
-h|--help)
print_help
exit 0
;;
--reset)
RESET=true
;;
--remove)
REMOVE=true
;;
--herolib)
HEROLIB=true
;;
--herolib-version=*)
HEROLIB_VERSION="${arg#*=}"
if [ -z "$HEROLIB_VERSION" ]; then
echo "Error: --herolib-version requires a version argument"
echo "Example: $0 --herolib-version=v1.0.0"
exit 1
fi
;;
--analyzer)
INSTALL_ANALYZER=true
;;
--start-redis)
START_REDIS=true
;;
*)
echo "Unknown option: $arg"
echo "Use -h or --help to see available options"
exit 1
;;
esac
done
myplatform
# Handle remove if requested
if [ "$REMOVE" = true ]; then
remove_all
exit 0
fi
# Create code directory if it doesn't exist
mkdir -p ~/code
# Check if v needs to be installed
if [ "$RESET" = true ] || ! command_exists v; then
update_system
install_packages
sshknownkeysadd
# Install secp256k1
v-install
fi
if [ "$START_REDIS" = true ]; then
start_redis_service
fi
if [ "$HEROLIB" = true ]; then
echo "=== Herolib Installation ==="
echo "Current directory: $(pwd)"
echo "Checking for install_herolib.vsh: $([ -f "./install_herolib.vsh" ] && echo "found" || echo "not found")"
echo "Checking for lib directory: $([ -d "./lib" ] && echo "found" || echo "not found")"
# Check if we're in GitHub Actions and already in the herolib directory
if is_github_actions; then
# In GitHub Actions, check if we're already in a herolib checkout
if [ -f "./install_herolib.vsh" ] && [ -d "./lib" ]; then
echo "✓ Running in GitHub Actions, using current directory for herolib installation"
HEROLIB_DIR="$(pwd)"
else
echo "⚠ Running in GitHub Actions, but not in herolib directory. Cloning..."
hero_lib_get
HEROLIB_DIR="$HOME/code/github/incubaid/herolib"
fi
else
echo "Not in GitHub Actions, using standard installation path"
hero_lib_get
HEROLIB_DIR="$HOME/code/github/incubaid/herolib"
fi
echo "Installing herolib from: $HEROLIB_DIR"
"$HEROLIB_DIR/install_herolib.vsh"
fi
if [ "$INSTALL_ANALYZER" = true ]; then
# Only install v-analyzer if not in GitHub Actions environment
if ! is_github_actions; then
v-analyzer
fi
echo "Run 'source ~/.bashrc' or 'source ~/.zshrc' to update PATH for v-analyzer"
fi
echo "Installation complete!"
}
main "$@"