Skip to content

Instantly share code, notes, and snippets.

@Mastersam07
Last active May 18, 2024 10:45
Show Gist options
  • Save Mastersam07/871073524516b81c0cd8156e564848ad to your computer and use it in GitHub Desktop.
Save Mastersam07/871073524516b81c0cd8156e564848ad to your computer and use it in GitHub Desktop.
Clean pub cache directories
#!/bin/bash

# Paths to the pub cache directories
PUB_CACHE_HOSTED_DIRS=("$HOME/.pub-cache/hosted/pub.dev" "$HOME/.pub-cache/hosted/pub.dartlang.org")
PUB_CACHE_HASHES_DIR="$HOME/.pub-cache/hosted-hashes/pub.dev"
PUB_CACHE_GIT_DIR="$HOME/.pub-cache/git"

# Function to clean old versions from a given directory
clean_old_versions() {
  local dir=$1

  if [ -d "$dir" ]; then
    cd "$dir" || exit
    processed_packages=()

    for package_dir in */; do
      package_name=$(basename "$package_dir" | sed -E 's/-[^-]+$//')
      # Skip if already processed
      if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
        continue
      fi

      processed_packages+=("$package_name")
      versions=($(ls -d "$package_name"-*/ 2>/dev/null | sort -V))

      if [ ${#versions[@]} -gt 0 ]; then
        latest_version=${versions[${#versions[@]}-1]}
        for version in "${versions[@]}"; do
          if [ "$version" != "$latest_version" ]; then
            echo "Removing old version: $version"
            rm -rf "$version"
          fi
        done
      fi
    done
  fi
}

# Function to clean old hashes
clean_old_hashes() {
  if [ -d "$PUB_CACHE_HASHES_DIR" ]; then
    cd "$PUB_CACHE_HASHES_DIR" || exit
    processed_packages=()

    for hash_file in *.sha256; do
      package_name=$(basename "$hash_file" | sed -E 's/-[^-]+$//')
      if [[ "$package_name" =~ ^[_] ]]; then
        continue
      fi
      # Skip if already processed
      if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
        continue
      fi

      processed_packages+=("$package_name")
      versions=($(ls "$package_name"-*.sha256 2>/dev/null | sort -V))

      if [ ${#versions[@]} -gt 0 ]; then
        latest_hash=${versions[${#versions[@]}-1]}
        for hash in "${versions[@]}"; do
          if [ "$hash" != "$latest_hash" ]; then
            echo "Removing old hash: $hash"
            rm -f "$hash"
          fi
        done
      fi
    done
  fi
}

# Function to clean the git cache directory
clean_git_cache() {
  if [ -d "$PUB_CACHE_GIT_DIR" ]; then
    cd "$PUB_CACHE_GIT_DIR" || exit
    processed_packages=()

    for package_dir in */; do
      if [ "$package_dir" != "cache/" ]; then
        package_name=$(basename "$package_dir" | sed -E 's/-[^-]+$//')
        # Skip if already processed
        if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
          continue
        fi

        processed_packages+=("$package_name")
        versions=($(ls -d "$package_name"-*/ 2>/dev/null | sort -V))

        if [ ${#versions[@]} -gt 0 ]; then
          latest_version=${versions[${#versions[@]}-1]}
          for version in "${versions[@]}"; do
            if [ "$version" != "$latest_version" ]; then
              echo "Removing old git package version: $version"
              rm -rf "$version"
            fi
          done
        fi
      fi
    done

    # Clean the cache folder inside the git directory
    if [ -d "cache" ]; then
      echo "Cleaning git cache folder"
      rm -rf cache/*
    fi
  fi
}

# Clean old versions from the hosted directories
for hosted_dir in "${PUB_CACHE_HOSTED_DIRS[@]}"; do
  clean_old_versions "$hosted_dir"
done

# Clean old hashes from the hosted-hashes directory
clean_old_hashes

# Clean the git cache directory
clean_git_cache

echo "Clean up completed. Only the latest versions and hashes of each package remain."

How to Use the Script

  • Save the script to a file, e.g., clean_pub_cache.sh.
  • Make the script executable:
chmod +x clean_pub_cache.sh
  • Run the script:
./clean_pub_cache.sh

Improved Script with Safeguards:

Here's an improved version of the script with additional safeguards:

#!/bin/bash

# Paths to the pub cache directories
PUB_CACHE_HOSTED_DIRS=("$HOME/.pub-cache/hosted/pub.dev" "$HOME/.pub-cache/hosted/pub.dartlang.org")
PUB_CACHE_HASHES_DIR="$HOME/.pub-cache/hosted-hashes/pub.dev"
PUB_CACHE_GIT_DIR="$HOME/.pub-cache/git"

# Function to prompt user for confirmation
confirm() {
  read -r -p "${1:-Are you sure? [y/N]} " response
  case "$response" in
    [yY][eE][sS]|[yY]) 
      true
      ;;
    *)
      false
      ;;
  esac
}

# Function to clean old versions from a given directory
clean_old_versions() {
  local dir=$1

  if [ -d "$dir" ]; then
    cd "$dir" || exit
    processed_packages=()

    for package_dir in */; do
      package_name=$(basename "$package_dir" | sed -E 's/-[^-]+$//')
      # Skip if already processed
      if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
        continue
      fi

      processed_packages+=("$package_name")
      versions=($(ls -d "$package_name"-*/ 2>/dev/null | sort -V))

      if [ ${#versions[@]} -gt 0 ]; then
        latest_version=${versions[${#versions[@]}-1]}
        for version in "${versions[@]}"; do
          if [ "$version" != "$latest_version" ]; then
            echo "Found old version: $version"
            if confirm "Do you want to remove $version? [y/N]"; then
              rm -rf "$version"
            fi
          fi
        done
      fi
    done
  fi
}

# Function to clean old hashes
clean_old_hashes() {
  if [ -d "$PUB_CACHE_HASHES_DIR" ]; then
    cd "$PUB_CACHE_HASHES_DIR" || exit
    processed_packages=()

    for hash_file in *.sha256; do
      package_name=$(basename "$hash_file" | sed -E 's/-[^-]+$//')
      if [[ "$package_name" =~ ^[_] ]]; then
        continue
      fi
      # Skip if already processed
      if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
        continue
      fi

      processed_packages+=("$package_name")
      versions=($(ls "$package_name"-*.sha256 2>/dev/null | sort -V))

      if [ ${#versions[@]} -gt 0 ]; then
        latest_hash=${versions[${#versions[@]}-1]}
        for hash in "${versions[@]}"; do
          if [ "$hash" != "$latest_hash" ]; then
            echo "Found old hash: $hash"
            if confirm "Do you want to remove $hash? [y/N]"; then
              rm -f "$hash"
            fi
          fi
        done
      fi
    done
  fi
}

# Function to clean the git cache directory
clean_git_cache() {
  if [ -d "$PUB_CACHE_GIT_DIR" ]; then
    cd "$PUB_CACHE_GIT_DIR" || exit
    processed_packages=()

    for package_dir in */; do
      if [ "$package_dir" != "cache/" ]; then
        package_name=$(basename "$package_dir" | sed -E 's/-[^-]+$//')
        # Skip if already processed
        if [[ " ${processed_packages[@]} " =~ " ${package_name} " ]]; then
          continue
        fi

        processed_packages+=("$package_name")
        versions=($(ls -d "$package_name"-*/ 2>/dev/null | sort -V))

        if [ ${#versions[@]} -gt 0 ]; then
          latest_version=${versions[${#versions[@]}-1]}
          for version in "${versions[@]}"; do
            if [ "$version" != "$latest_version" ]; then
              echo "Found old git package version: $version"
              if confirm "Do you want to remove $version? [y/N]"; then
                rm -rf "$version"
              fi
            fi
          done
        fi
      fi
    done

    # Clean the cache folder inside the git directory
    if [ -d "cache" ]; then
      echo "Found git cache folder"
      if confirm "Do you want to clean the git cache folder? [y/N]"; then
        rm -rf cache/*
      fi
    fi
  fi
}

# Clean old versions from the hosted directories
for hosted_dir in "${PUB_CACHE_HOSTED_DIRS[@]}"; do
  clean_old_versions "$hosted_dir"
done

# Clean old hashes from the hosted-hashes directory
clean_old_hashes

# Clean the git cache directory
clean_git_cache

echo "Clean up completed. Only the latest versions and hashes of each package remain."

Improvements and Safeguards

  • Confirmation Prompt: Added a confirm function to prompt the user for confirmation before deleting any files. This adds a safeguard against accidental deletion.
  • Manual Intervention: By confirming each deletion, you have more control over what gets removed, reducing the risk of breaking dependencies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment