Rename java packages on all branches: script.
Tags: java, bash, programming, git
Published: 2023-08-10 09:30:40

Found yourself in need of a script that loops through all branches in a project and renames the package name? No? 

It's a bit of a strange situation to be in I grant you, but if you have a project with a lot of branches for some strange reason, and you'd like to change the name / structure of your package. Then this is the script for you! 

This scripts takes the paramaters: <old.package.name> <new.package.name> <path/to/project/root> 
Nested packages work just as well. 

NOTE: it also pushes on all branches, please comment it out on the first try run. 

```bash
#!/bin/bash

# Script made to loop though the src/main/java and the src/test/java directories and rename
# the packages based on the input. 
# Example: sh renameJavaPackages.sh to.dev.bacongubbe dev.bacongubbe.example /Users/bacongubbe/Projects/peskyproject

if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then
    echo "Usage: $0 <old_package> <new_package> <repository_path>"
    echo "   - old_package: The old package name, ex: 'to.dev.bacongubbe'."
    echo "   - new_package: The new package name to use in package structure. Ex: dev.bacongubbe.example"
    echo "   - repository_path: Path to the repository where the changes should be made"
    exit 0
fi

if [ $# -ne 3 ]; then
    echo "Error: Incorrect number of arguments. Use --help for usage information."
    exit 1
fi

old_package="$1"
new_package="$2"
repository_path="$3"

cd "$repository_path" || exit

for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
    git checkout $branch
    echo "## Switched to $branch branch"

    for directory in "src/main/java" "src/test/java"; do
                echo "Package $old_package is being replaced with $new_package in $directory"

        find "$directory" -name "*.java" -type f -exec sed -i '' -e "s@$old_package@$new_package@g" {} +

        # Rename package directories
        old_dir="${old_package//.//}"
        new_dir="${new_package//.//}"
        mkdir -p "$directory/$new_dir"
        echo "dir $directory/$new_dir made"
        echo "copying contents from $directory/$old_dir to $directory/$new_dir"
        cp -r "$directory/$old_dir"/* "$directory/$new_dir"

        # Loop through the old and new structure and returns the first directory that is not matching. 
        # Ex: if you're renaming se.company.coolapp to se.company.coolerapp, it will return ../company/coolapp, since the se/company/ is the 
        # same in both.
        IFS="/" read -ra old_dir_parts <<< "$old_dir"
        IFS="/" read -ra new_dir_parts <<< "$new_dir"
        first_diff_dir=""
        for ((i=0; i<${#old_dir_parts[@]} && i<${#new_dir_parts[@]}; i++)); do
            if [ "${old_dir_parts[i]}" != "${new_dir_parts[i]}" ]; then
                first_diff_dir="${first_diff_dir}/${old_dir_parts[i]}"
                break
            fi
            first_diff_dir="${first_diff_dir}/${old_dir_parts[i]}"
        done
       echo "deleting: $directory${first_diff_dir}"
     
     # makes sure that there is a directory that needs to be deleted. 
       if [ -n "$first_diff_dir" ]; then
         rm -rf "$directory$first_diff_dir"
       fi
    done
    git add .
    git commit -m "Chore: Rename packages in $branch from $old_package to $new_package"

    # Push the changes to the remote repository
    git push origin $branch
done


```

Hope it helps!