forked from vitorgalvao/tiny-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
prfixbranch
executable file
·122 lines (105 loc) · 3.46 KB
/
prfixbranch
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
#!/bin/bash
readonly program="$(basename "${0}")"
readonly commit_hash_file="/tmp/prfix_hash_save"
readonly issue_number_file="/tmp/prfix_issue_number_save"
remote='upstream' # use 'upstream' as default remote
syntax_error() {
echo -e "${program}: ${1}\nTry \`${program} --help\` for more information." >&2
exit 1
}
usage() {
echo "
Usage:
${program} [options] <github_pull_request_url>
Options:
-r <remote>, --remote <remote> Use to specify a remote to push to (defaults to 'upstream').
-c, --continue Use after making your fixes, to push your changes. If you use it with uncommitted changes, they'll all be squashed (fixup) into the original patch; else your commits will be preserved.
-h, --help Show this help.
" | sed -E 's/^ {4}//'
}
# read remote from git config
configured_remote="$(git config --get tiny-scripts.remote)"
if [[ -n "${configured_remote}" ]]; then
remote="${configured_remote}"
fi
# available flags
args=()
while [[ "${1}" ]]; do
case "${1}" in
-h | --help)
usage
exit 0
;;
-r | --remote)
remote="${2}"
shift
;;
-c | --continue)
push_changes="yes"
;;
--)
shift
args+=("${@}")
break
;;
-*)
syntax_error "unrecognized option: ${1}"
;;
*)
args+=("${1}")
;;
esac
shift
done
set -- "${args[@]}"
check_repo() {
local_repo=$(git remote show origin -n | grep 'Fetch URL:' | sed 's|.*/||;s|\.git$||')
remote_repo=$(sed -E 's|.*/(.*)/pull.*|\1|' <<< "${url}")
if [[ "${local_repo}" != "${remote_repo}" ]]; then
echo -e "\n$(tput setaf 1)You're trying to pull from '${remote_repo}' but you're on '${local_repo}'.$(tput sgr0)\n"
exit 1
fi
}
apply_patch() {
url=$(perl -pe 's|(.*/pull/\d+).*|\1|' <<< "${1}") # clean url of extraneous information
issue_number=$(sed 's|.*/||' <<< "${url}")
patch_url="${url}.patch" # github pull request url, ending in '.patch'
check_repo
branch_name="fix-${issue_number}"
git checkout -b "${branch_name}"
curl --location --silent "${patch_url}" | git am --3way # get and apply patch
git rev-parse HEAD > "${commit_hash_file}" # save hash from current commit
echo "${issue_number}" > "${issue_number_file}" # save issue number
echo "
Make your necessary changes, and run
${program} -c
If you have uncommitted changes, they'll be squashed into the original patch.
If you have new commits, they’ll be included separately
" | sed -E 's/^ {2}//'
}
push_changes() {
original_commit="$(cat ${commit_hash_file})"
original_issue="#$(cat ${issue_number_file})"
branch_name="$(git rev-parse --abbrev-ref HEAD)"
uncommitted_changes="$(git status --porcelain --untracked-files=no)"
# squash your fixes into the original patch, if there are uncommitted changes
if [[ "${uncommitted_changes}" ]]; then
git commit --all --allow-empty-message --message ''
git reset --soft "${original_commit}"
# add message to close the original pull request
original_commit_message="$(git log --oneline -1 | cat - | sed -E 's/^[^ ]* //')"
git commit --amend --message "${original_commit_message}" --message "Closes ${original_issue}."
fi
# push and delete branch
git push "${remote}" "${branch_name}"
git checkout master
git branch -D "${branch_name}"
}
if [[ "${1}" =~ https://github.com/* ]]; then
apply_patch "${1}"
elif [[ "${push_changes}" == 'yes' ]]; then
push_changes
else
usage
exit 1
fi