test_publish.sh (9362B)
1 #!/bin/sh 2 3 # Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 set -ex 19 20 die() 21 { 22 rm -rf "${tmpdir}" # cleanup temporary files 23 return "${1:-1}" # return status code (default is 1) 24 } 25 26 # Configure signal processing 27 trap 'die $?' EXIT 28 trap 'die 1' TERM INT 29 30 cookie='D3CAFBAD' 31 name="repo" 32 33 # Working directory 34 tmpdir="$(mktemp -d "${TMPDIR:-/tmp}"/git_publish_test_XXXXXX)" 35 repo="${tmpdir}/${name}" 36 git="${tmpdir}/git/${name}.git" 37 srv="${tmpdir}/srv" 38 39 # Use the local git-publish 40 export PATH="${PWD}:${PATH}" 41 42 ######################################################################## 43 # Helper functions 44 ######################################################################## 45 check_git_content() # repo-url 46 { 47 git clone "$1" "${tmpdir}/${name}" 48 49 [ -f "${tmpdir}/${name}/README" ] 50 [ -f "${tmpdir}/${name}/cookie.txt" ] 51 52 str="$(cat "${tmpdir}/${name}/cookie.txt")" 53 [ "${str}" = "${cookie}" ] 54 55 rm -rf "${tmpdir:?}/${name}" 56 } 57 58 get_group() # file 59 { 60 # shellcheck disable=SC2012 61 ls -dl "$1" | cut -d' ' -f4 62 } 63 64 get_group_perms() # file 65 { 66 # shellcheck disable=SC2012 67 ls -dl "$1" | cut -d' ' -f1 | cut -c5-7 68 } 69 70 check_www_content_perm() # group, [fperm, dperm] 71 { 72 # Check file permissions 73 find -L "${srv}/www/" \ 74 -path "${srv}/www/${name}/*" -o -name "index.html" \ 75 | while read -r i; do 76 _group="$(get_group "${i}")" 77 _perm="$(get_group_perms "${i}")" 78 79 if [ -L "${i}" ]; then # Do not check symbolic links 80 continue 81 fi 82 83 [ "${_group}" = "$1" ] || return 1 84 85 if [ -z "$2" ] || [ -z "$3" ]; then 86 # Do not check group's permissions 87 continue 88 fi 89 90 # Check group's permissions 91 if [ -d "${i}" ]; then 92 [ "${_perm}" = "$3" ] || return 1 # Directory 93 else 94 _p="$(printf '%s\n' "${_perm}" | cut -c1,2)" 95 [ "${_p}" = "$2" ] || return 1 # File 96 fi 97 done 98 } 99 100 check_www_content() 101 { 102 [ -f "${srv}/www/index.html" ] 103 [ -d "${srv}/www/${name}" ] 104 [ -f "${srv}/www/${name}/index.html" ] 105 } 106 107 ######################################################################## 108 # Setup repository 109 ######################################################################## 110 # Create bare repository 111 mkdir -p "${git}" 112 git init --initial-branch=master --bare "${git}" 113 114 # Create the repository content 115 mkdir -p "${repo}" 116 printf 'Repository to be published\n' > "${repo}/README" 117 printf '%s' "${cookie}" > "${repo}/cookie.txt" 118 119 # Configure the directory as a git working directory, commit its 120 # content and push it to the remote repository 121 cd "${repo}" 122 git init --initial-branch=master 123 git config --local user.name "Mr Untel" 124 git config --local user.email "mr@untel.fr" 125 git add README cookie.txt 126 git commit -m "Test content for publishing a repository" 127 git remote add origin "file://${git}" 128 git push origin master 129 130 cd "${OLDPWD}" 131 rm -rf "${repo}" # Remove temporary directory 132 133 ######################################################################## 134 # Basic tests 135 ######################################################################## 136 # Publish the repository 137 mkdir -p "${srv}/git" "${srv}/www" 138 git publish \ 139 -g "${srv}/git" \ 140 -w "${srv}/www" \ 141 -u "http://mr.untel.fr/" \ 142 "${git}" 143 144 [ -L "${srv}/git/${name}.git" ] # The published repository is a symlink 145 146 check_git_content "file://${srv}/git/${name}.git" 147 check_git_content "file://${git}" 148 check_www_content 149 150 # Try to publish an already published repository 151 git publish \ 152 -g "${srv}/git" \ 153 -w "${srv}/www" \ 154 -u "http://mr.untel.fr/" \ 155 "${git}" 156 157 # Unpublish 158 GIT_PUBLISH_DIR_GIT="${srv}/git" \ 159 GIT_PUBLISH_DIR_WWW="${srv}/www" \ 160 git publish -d "${git}" 161 162 # Attempting to unpublish a non-published repository results in an error 163 ! git publish -d "${git}" -g "${srv}/git" -w "${srv}/www" || die 1 164 165 # The published content should be removed 166 [ ! -e "${srv}/git/${name}.git" ] 167 [ ! -e "${srv}/www/${name}" ] 168 [ ! -e "${srv}/www/index.html" ] # No more index since no more repo 169 170 check_git_content "file://${git}" # Original repository should be OK 171 172 ######################################################################## 173 # Test the publication by moving the source repository 174 ######################################################################## 175 export GIT_PUBLISH_DIR_GIT="${srv}/git" 176 export GIT_PUBLISH_DIR_WWW="${srv}/www" 177 export GIT_PUBLISH_BASE_URL="http://mr.untel.fr" 178 179 # Publish the repository by moving it to the publicly accessible 180 # directory and converting the original repository into a symbolic link 181 # to the public repository 182 git publish -m "${git}" 183 184 # The public repository is a directory, not a symbolic link 185 [ -d "${srv}/git/${name}.git" ] && [ ! -L "${srv}/git/${name}.git" ] 186 187 # The original repository is a symbolic link to the public repository 188 [ -L "${git}" ] 189 190 check_git_content "file://${srv}/git/${name}.git" 191 check_git_content "file://${git}" 192 check_www_content 193 194 # Republish the same repo but without the -m option. 195 # Check that the public repo is thus a symbolic link to the original 196 # repository 197 git publish "${git}" 198 [ -L "${srv}/git/${name}.git" ] 199 [ -d "${git}" ] && [ ! -L "${git}" ] 200 201 # Republish the same repo with the -m option. 202 # Check that the original path is a symbolic link to the public 203 # repository 204 git publish -m "${git}" 205 [ -d "${srv}/git/${name}.git" ] && [ ! -L "${srv}/git/${name}.git" ] 206 [ -L "${git}" ] 207 208 # Unpublish the repository 209 git publish -d "${git}" 210 211 # The published content should be removed 212 [ ! -e "${srv}/git/${name}.git" ] 213 [ ! -e "${srv}/www/${name}" ] 214 [ ! -e "${srv}/www/index.html" ] # No more index since no more repo 215 216 # And the original repository should be a directory, not a symbolic 217 [ -d "${git}" ] && [ ! -L "${git}" ] 218 219 check_git_content "file://${git}" 220 221 ######################################################################## 222 # The repository cannot be [un]published 223 ######################################################################## 224 # Prevent the publication of the repository 225 touch "${git}/publication_ban" 226 227 git publish "${git}" 228 [ ! -e "${srv}/git/${name}.git" ] 229 [ ! -e "${srv}/www/${name}" ] 230 231 git publish -m "${git}" 232 [ ! -e "${srv}/git/${name}.git" ] 233 [ ! -e "${srv}/www/${name}" ] 234 235 # Make the repository publishable 236 rm "${git}/publication_ban" 237 238 # The repository cannot be published if the public path exists and it is 239 # not the result of an earlier publication of the reposite. It cannot 240 # unpublised too. 241 touch "${srv}/git/${name}.git" 242 ! git publish "${git}" || die 1 243 ! git publish -d "${git}" || die 1 244 rm "${srv}/git/${name}.git" 245 mkdir "${srv}/git/${name}.git" 246 ! git publish "${git}" || die 1 247 ! git publish -d "${git}" || die 1 248 rmdir "${srv}/git/${name}.git" 249 250 ######################################################################## 251 # Switch from the original repository to the published repository 252 ######################################################################## 253 # Publish the repository and try to unpublish the original repository. 254 # The original repository has been deleted! But the one that was 255 # published should still be valid as it was considered as the original 256 # one . 257 git publish -g "${srv}/git/" "${git}" 258 git publish -g "$(dirname "${git}")" -d "${srv}/git/${name}.git" 259 [ ! -e "${git}" ] 260 check_git_content "file://${srv}/git/${name}.git" 261 mv "${srv}/git/${name}.git" "${git}" 262 check_git_content "file://${git}" 263 264 # Same as above but the published repository is the original one moved 265 # to the public directory 266 git publish -g "${srv}/git/" -m "${git}" 267 git publish -g "$(dirname "${git}")" -d "${srv}/git/${name}.git" 268 [ ! -e "${git}" ] 269 check_git_content "file://${srv}/git/${name}.git" 270 271 # Restore the original repository 272 mv "${srv}/git/${name}.git" "${git}" 273 274 ######################################################################## 275 # Grant write access to the WWW content 276 ######################################################################## 277 # Find another group that is not the user's group, but to which the user 278 # belongs. Fails if such group is not found, even though this situation 279 # is perfectly valid from the system's perspective, because the test 280 # cannot actually be performed. 281 group="$(id -gn)" 282 group="$(id -Gn | tr ' ' '\n' | grep -v "${group}" | head -n1)" 283 [ -n "${group}" ] 284 285 # Grant the group write access to the WWW content 286 git publish -s "${group}" "${git}" 287 check_www_content_perm "${group}" "rw" "rws" 288 289 # Republishing without the -s option does not guarantee that the group's 290 # write permissions will be preserved or that they will be reset 291 git publish "${git}" 292 # shellcheck disable=SC2310 293 ! check_www_content_perm "${group}" "rw" "rws" || die 1 294 group="$(id -gn)" 295 # shellcheck disable=SC2310 296 ! check_www_content_perm "${group}" || die 1 297 298 # Republish with the -f option ensure that the file permissions are set 299 # to the default values 300 git publish -f "${git}" 301 check_www_content_perm "${group}" 302 303 die 0