summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/.local/bin/git-split.sh
blob: ecb2b3a584c1e474c67ebcb09d63dc125036d6d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env bash

TEMP=$(getopt -o hvdymu:r: --long help,verbose,debug,submodule,remote:,username:,visibility: \
    -n 'javawrap' -- "$@")

if [ $? != 0 ]; then
    echo "Terminating..." >&2
    exit 1
fi

if ! git rev-parse --is-inside-work-tree &>/dev/null; then
    echo "Must be run inside a git repository" >&2
    exit 1
fi

eval set -- "$TEMP"

SCRIPT="$(basename $0)"
ARTIFACTS=(".gitignore" ".gitattributes" ".vscode" "LICENSE")
VERBOSE=false
DEBUG=false
CONFIRMED=false
SUBMODULE=false
REPO=$(git rev-parse --show-toplevel)
USERNAME="$(git config user.username)"
REMOTE=
VISIBILITY="--public"

read -r -d '' USAGE <<-EOF
USAGE: $SCRIPT [OPTIONS]

OPTIONS:
    -h, --help                          Show this message
    -v, --verbose                       Show more output
    -d, --debug                         NOT IMPLEMENTED
    -y, --confirm                       Do not prompt for confirmation
    -m, --submodule                     
            Migrate directory in original repository to submodule

    -u, --username=<user/repo>         
            Github username. Can be used instead of remote to dynamically name 
            the repositories. If --username and --remote are both ommited, defaults 
            to $(git config user.username)

    -r, --remote=<user/repo>         
            Github remote, defaults to ${username}/${directory}

        --private                       
            Create the new remote repository as private. It is created 
            as public if ommited

ARGS:
    <DIRECTORY>...  Directory to split out of original repository, 
                    defaults to current directory
EOF

while true; do
    case "$1" in
    -h | --help)
        echo "$USAGE"
        exit 0
        ;;
    -v | --verbose)
        VERBOSE=true
        shift
        ;;
    -d | --debug)
        DEBUG=true
        shift
        ;;
    -y)
        CONFIRMED=true
        shift
        ;;
    -m | --submodule)
        SUBMODULE=true
        shift
        ;;
    -u | --username)
        USERNAME="$2"
        shift 2
        ;;
    -r | --remote)
        REMOTE="$(basename $(dirname ${2#"git@github.com:"}))/$(basename ${2#"git@github.com:"})"
        shift 2
        ;;
    --public | --private)
        VISIBILITY="$1"
        shift
        ;;
    --)
        shift
        break
        ;;
    *)
        break
        ;;
    esac
done

DIRECTORY="${1:-$(realpath --relative-to="$REPO" .)}"

if [ ! -d "${REPO}/${DIRECTORY}" ]; then
    echo "ERROR: Directory does not exist." >&2
    echo "$USAGE"
    exit 1
fi

if [ -z "$REMOTE" ]; then
    if [ -z "$USERNAME" ]; then
        echo "ERROR: No remote provided and user.username was not set." >&2
        echo "$USAGE"
        exit 1
    else
        REMOTE="${USERNAME}/${DIRECTORY}"
    fi
fi

set -e

cd $REPO

git subtree split -P $DIRECTORY -b $DIRECTORY

cd "$(mktemp -d)"

git init && git pull $REPO $DIRECTORY && git branch -M main

for f in "${ARTIFACTS[@]}"; do
    if [[ ! -e "./${f}" && -e "${REPO}/${f}" ]]; then
        printf '%s\n' "Copying ${f} to new repository..."
        cp -r "${REPO}/${f}" ./
    fi
done

git add -A && git commit -m "split out $DIRECTORY into submodule"

# TODO check if remote already exists
if command -v gh &>/dev/null; then
    yes "n" | gh repo create --confirm "${REMOTE}" "${VISIBILITY}"
else
    printf '%s\n' 'gh cli tool could not be found. Explicitly adding git remote to your local repository.'

    git remote add origin https://github.com/${REMOTE}
fi

set +e

git push -u origin main

if [ $? -ne 0 ]; then
    printf '\n%s\n' 'Verify/create the remote repository and push to it with the following command: '
    printf '\n\t%s%s%s\n\n' '`cd ' "$(pwd)" ' && git push -u origin main`'

    printf '\t%s\n' \
        '*********************************************************************************' \
        '* The new repository was created in a temp directory!                           *' \
        '* If the local repository is not pushed to remote, it will be lost on reboot.   *' \
        '*********************************************************************************'
else
    tempdir="$(pwd)"
    cd "$REPO"
    rm -rf "$tempdir"
fi

# Migrate to submodule

if [ "$SUBMODULE" != true ]; then
    exit 0
fi

# TODO fix and remove warning

printf 'Migrating the original subdirectory to submodule.\n'

if [ "$QUIET" != true ]; then
    printf '\t%s\n' \
        '*************************************************************************************' \
        '*  THIS IS NOT TESTED AND HAS A POSSIBLY OF DATA LOSS!                              *' \
        '*                                                                                   *' \
        '*  This runs `git rm -rf` and `rm -rf` on the original subdirectory.                *' \
        '*  Double check you succesfully migrated the subdirectory to the new repository.    *' \
        '*************************************************************************************'
fi

if [ "$CONFIRMED" != true ]; then
    read -p "Proceed? (Y/n) " -n 1 -r
    printf '\n'
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        CONFIRMED=true
    else
        [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1
    fi
fi

cd $REPO

git rm -rf $DIRECTORY
rm -rf $DIRECTORY

git submodule add git@github.com:$REMOTE $DIRECTORY
git submodule update --init --recursive

git commit -m "split out $DIRECTORY into submodule"

if [ $? -ne 0 ]; then
    printf '%s\n' 'Submodule succesfully added. Be sure to `git push -u origin main` after verifing the migration.'
fi