aboutsummaryrefslogtreecommitdiff
path: root/gc2gs.sh
blob: 7e79ff082b76a7ebb495c0455da6ef60c4510b98 (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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/bin/sh
# -*- ENCODING: UTF-8 -*-
# gc2gs - Git Commit to Gnu-Social
# Post last git-project commit info to gnu-social
# Author: ziggys
# License: The Drunken BEER License v 1.1 (https://git.p4g.club/git/beer/about)

# scriptinfo
SCRIPTNAME="${0##*/}"
SCRIPTNAME="${SCRIPTNAME%%.sh}"
VERSION="1.0.2"		                         # Add some basic tests
AUTHOR="ziggys"
LICENSE="The Drunken BEER License v 1.1 (https://git.p4g.club/git/beer/about)"

# show help
show_help () {
test "${#}" = 0 || echo "${@}"
echo "${SCRIPTNAME} version ${VERSION}"
echo "  by ${AUTHOR}"
echo "  License: ${LICENSE}"
echo
echo "${SCRIPTNAME} is a shellscript that posts a status message to a"
echo "  gnu-social node with the last commit information of a git-project"
echo 
echo "Usage:  ${0} [OPTIONS] <args> ..."
echo "Usage:  ${0} [-[ckp]vh] projectname"
echo
echo "Options"
echo "   -c   <projectname>   Create a configuration file for 'projectname'"
echo "   -k   <projectname>   Create a 'pre-push' 'git hook' for 'projectname'"
echo "   -p   <projectname>   Post a status message with 'projectname'"
echo "                        last commit information. Usefull when running"
echo "                        the script manually"
echo "   -v   VERBOSE         Increase verbosity" 
echo "   -h   HELP            Print this help and exit"
echo
echo "For more details about this script go to"
echo "Official Repository: https://git.p4g.club/git/gc2gs"
echo "Mirror Repository: https://gitgud.io/ziggys/gc2gs"
exit "${?}"
}

# configure new project.config
configure () {
  printf "Configuring a new project.config file for %s\\n" "${CONFNAME}"

  test -f "${RCFILE}" \
    && printf "%s already exists...\\ndo you want to overwrite? " "${RCFILE}" \
    && printf "[yes to create a new one] (yes/no): " \
    && read -r OVERANS \
    || echo "" > "${RCFILE}"

  test "${OVERANS}" = "no" \
    && printf "you will be using old project.config file\\n" \
    && exit "${?}" \
    || echo "" > "${RCFILE}"

  printf "\\nPlease enter your gnu-social account information\\n"
  printf "'username' (i.e. 'me@myno.de', 'username=me'): " \
    && read -r CONFUNAME
  printf "'password' (your 'plain-text password'): " \
    && read -r CONFPASS
  printf "'node' (url w/o trainling slash 'https://myno.de'): " \
    && read -r CONFNODE
  # obfuscate user and password
  CONFUNAME="$(echo "${CONFUNAME}" | base64 -)"
  CONFPASS="$(echo "${CONFPASS}" | base64 -)"

  printf "\\nPlease enter your git project information\\n"
  printf "git project (the name of your git repository): " \
    && read -r CONFPROJ
  printf "project url (https://git.reposito.ry/me/project): " \
    && read -r CONFPURL
  printf "project path (i.e. %s/git/myrepo ): " "${HOME}" \
    && read -r REPOPATH
  printf "platform (cgit | gitlab | github | gitea | other): " \
    && read -r CONFPLAT
  
  printf "\\nPopulating %s...\\n" "${RCFILE}"
  printf "USER=%s;\\nPASSWORD=%s;\\nNODE=%s;\\n" \
    "${CONFUNAME}" "${CONFPASS}" "${CONFNODE}" >> "${RCFILE}"
  printf "PROJECT=%s;\\nPROJECTURL=%s;\\nREPOPATH=%s;\\nPLATFORM=%s;\\n" \
    "${CONFPROJ}" "${CONFPURL}" "${REPOPATH}" "${CONFPLAT}" >> "${RCFILE}"

  # this file stores passwords, securize permissions
  chmod 600 "${RCFILE}"

  printf "\\ndo you want to configure a 'pre-push' 'git hook'? (yes/no):  " \
    && read -r HOOKANS
  test "${HOOKANS}" = "no" \
    && printf "done!\\n" \
    && exit "${?}" \
    || hook_config
}

# configure a pre-push git hook
hook_config () {
  sed 's/nullconfname/'"${CONFNAME}"'/' "${SNIPPET}" > "$CPREPUSH"
  printf "\\nConfiguring a 'pre-push' 'git hook' for %s\\n" "${CONFNAME}"

  test ! -d "${REPOPATH}" \
    && printf "\\n%s is not a directory... exiting" "${REPOPATH}" \
    && exit "${?}" \
    || isgit

  test ! -z "${ISGIT}" \
    && chmod +x "${CPREPUSH}" \
    && cp "${CPREPUSH}" "${REPOPATH}/${HOOKPATH}" \
    && printf "\\ndone!" 

  exit 0
}

# check if the repopath is a git repository
isgit () {
  cd "${REPOPATH}" || echo "${REPOPATH}" > /dev/null
  git rev-parse > /dev/null
  test "${?}" -ne 0 \
    && printf "\\n%s is not a git repository, exiting..." "${REPOPATH}" \
    && exit "${?}" \
    || ISGIT="notnull"
}

# basic tests
basic_tests () {
test ! -d "${CONFIGDIR}" && mkdir -p "${CONFIGDIR}"
test ! -f "${RCFILE}" \
  && printf "It seems you don't have a configuration file for %s\\n" \
    "${CONFNAME}" \
  && printf "Do you want to configure it know? " \
  && printf "(answering 'no' will exit script) (yes/no):  " \
  && read -r ANSFORCONFIG \
  || echo "RCFILE exists" > /dev/null

test "${ANSFORCONFIG}" = "yes" && configure || exit 0
}

status_config () {
# project variables
  cd "${REPOPATH}" || echo "${REPOPATH}" > /dev/null
  BRANCH="$(git branch | sed '/^*/ !d; s/* //')"
  COMMITMSG="$(git log -1 --pretty=%B)"
  COMMITTER="$(git log -1 | sed '/Author:/ !d; s/Author: //; s/<*[ \t].*//')"
  COMMITDATE="$(git log -1 | sed '/Date/ !d; s/Date:.[ \t].//; s/-.*//')"
  COMMITDATE="$(date --date "${COMMITDATE}" "+%d-%m %H:%M")"
  COMMITID="$(git log -1 | sed '/commit/ !d; s/commit //')"

  # url variables
  GITURI="commit/${COMMITID}"
  CGITURI="commit/?h=${BRANCH}"
  case "${PLATFORM}" in
    cgit) COMMITURI="${CGITURI}" ;;
    *) COMMITURI="${GITURI}" ;;
  esac
  COMMITURL="${PROJECTURL}/${COMMITURI}"

  # status message
  TTITLE="${TTITTLE:="The ${PROJECT} project"}"
  printf "%s\\n\\n | New commit on branch %s by %s (at %s):\\n\\n" \
    "${TTITLE}" "${BRANCH}" "${COMMITTER}" "${COMMITDATE}" >> "${TSTATUS}"
  printf "%s (%s)\\n\\ncommit_url: %s\\n\\nproject_url: %s" \
    "${COMMITMSG}" "${COMMITID}" "${COMMITURL}" "${PROJECTURL}" >> "${TSTATUS}"
  STATUS="$(cat "${TSTATUS}")"
}

# post
gs_post () {
  status_config
  # deobfuscate user and pass
  USER="$(echo "${USER}" | base64 --decode -)"
  PASSWORD="$(echo "${PASSWORD}" | base64 --decode -)"
  PME="A status message was posted on ${NODE} by ${USER}"
  NPME="An error ocurred posting on ${NODE}"

  curl -s -u "$USER:$PASSWORD" --data-urlencode status="${STATUS}" \
    -d source="${SCRIPTNAME}" "${NODE}/api/statuses/update.xml" > "${VOUTPUT}"

  test "$?" -lt 1 && printf "%s\\n" "${PME}" || printf "%s\\n" "${NPME}"
  test ! -z "${VERBOSE}" && cat "${VOUTPUT}"
}

# read options from commandline
test "${#}" -lt 1 && show_help "${@}"
while getopts ":c:k:p:vh" opt; do
  case "${opt}" in
    c) CONFNAME="${OPTARG}" ; EXECUTE="config" ;;
    k) CONFNAME="${OPTARG}" ; EXECUTE="hook" ;;
    p) CONFNAME="${OPTARG}" ; EXECUTE="post" ;;
    \?) printf "Invalid: -%s" "${OPTARG}" 1>&2 ; exit 3 ;;
    :) printf "Invalid: -%s requires an argument" "${OPTARG}" 1>&2 ; exit 3 ;;
    v) VERBOSE="notnull" ;;
    h) show_help "${@}";;
  esac
done
shift $((OPTIND -1))

# create temp files for operation
TMPDIR="$(mktemp -d)"
CPREPUSH="$(mktemp -p "${TMPDIR}")"
INPUT="$(mktemp -p "${TMPDIR}")"
TSTATUS="$(mktemp -p "${TMPDIR}")"
VOUTPUT="$(mktemp -p "${TMPDIR}")"

# configure variables
test -z "${CONFNAME}" && show_help "${@}"
XDGCONF="${XDG_HOME_CONFIG:=${HOME}/.config}"
CONFIGDIR="${XDGCONF}/gc2gs"
RCFILE="${CONFIGDIR}/${CONFNAME}.config"
test ! -d "${CONFIGDIR}" && basic_tests
test ! -f "${RCFILE}" && basic_tests
SNIPPET="snippet/snippet"
HOOKPATH=".git/hooks/pre-push"

# input variables
sed '/^#/ d; s/;[ \t].*//g; s/;$//g; s/[ \t]*$//g' "${RCFILE}" > "${INPUT}"

USER="$(sed '/USER=/ !d; s/USER=//' "$INPUT")"
PASSWORD="$(sed '/PASSWORD=/ !d; s/PASSWORD=//' "$INPUT")"
NODE="$(sed '/NODE=/ !d; s/NODE=//' "$INPUT")"
PROJECT="$(sed '/PROJECT=/ !d; s/PROJECT=//' "$INPUT")"
PROJECTURL="$(sed '/PROJECTURL=/ !d; s/PROJECTURL=//' "$INPUT")"
REPOPATH="$(sed '/REPOPATH=/ !d; s/REPOPATH=//' "$INPUT")"
PLATFORM="$(sed '/PLATFORM=/ !d; s/PLATFORM=//' "$INPUT")"

# check options and execute
case "${EXECUTE}" in
  config) configure ;;
  hook) hook_config ;;
  post) gs_post ;;
esac

# clean and exit
rm -rf "${TMPDIR}"
exit 0