Last active
May 8, 2024 14:15
-
-
Save jorsn/398ba31ac6fbfcf1c25eb6e0e07a3773 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # This script sets up git similar to the git bridge of Overleaf. It is based on | |
| # instructions by Tobias Bora (https://github.com/sagemathinc/cocalc/issues/3811#issuecomment-493138304). | |
| # If the repository and git hooks do not exist, they are created. | |
| # If they do exist, then this script tells you about config conflicts and how to | |
| # resolve them. | |
| # | |
| # | |
| # Usage: | |
| # | |
| # 1. Copy this file to your cocalc project, e.g. via ssh, | |
| # or copy it to the clipboard, type in a terminal in cocalc | |
| # | |
| # $ cat <<'EOS' > git-bridge-setup.sh | |
| # <paste clipboard, e.g. Ctrl+v> | |
| # EOS | |
| # | |
| # 2. run it (e.g. 'bash git-bridge-setup.sh') | |
| # Optionally, you can specify the GIT_PROJECT_PATH (Default: 'repo'): | |
| # | |
| # $ GIT_PROJECT_PATH=foo bash git-bridge-setup.sh | |
| # | |
| # It is either absolute or interpreted relative to the home directory. | |
| # | |
| # | |
| # MIT License | |
| # | |
| # Copyright (c) Johannes Rosenberger | |
| # | |
| # Permission is hereby granted, free of charge, to any person obtaining a copy | |
| # of this software and associated documentation files (the "Software"), to deal | |
| # in the Software without restriction, including without limitation the rights | |
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| # copies of the Software, and to permit persons to whom the Software is | |
| # furnished to do so, subject to the following conditions: | |
| # | |
| # The above copyright notice and this permission notice shall be included in all | |
| # copies or substantial portions of the Software. | |
| # | |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| # SOFTWARE. | |
| GIT_PROJECT_PATH="${GIT_PROJECT_PATH:-repo}" | |
| cd /home/user | |
| mkdir -p bin "$GIT_PROJECT_PATH" | |
| ######################### | |
| # set up git-server-hooks | |
| maybe_continue_ask() { | |
| echo -n "Continue (y/*)? " >&2 | |
| read response | |
| if [ "$response" == y ]; then | |
| echo "Continuing..." >&2 | |
| else | |
| echo "Exiting." >&2 | |
| exit | |
| fi | |
| } | |
| write_hook() { | |
| file="/home/user/bin/$1" | |
| content="$2" | |
| if [ -f "$file" ]; then | |
| echo "cocalc-setup-git-bridge: warning: file '$file' exists. Please set up hook manually:" >&2 | |
| echo '' | |
| echo "$content" | sed 's/^/ /' | |
| echo '' | |
| maybe_continue_ask | |
| else | |
| echo "$content" > "$file" | |
| chmod u+x "$file" | |
| fi | |
| } | |
| write_hook git-upload-pack "$(cat <<EOF | |
| #!/usr/bin/env bash | |
| GIT_PROJECT_PATH="\${GIT_PROJECT_PATH:-$GIT_PROJECT_PATH}" | |
| (>&2 echo "====== Let's first commit if needed =====") | |
| cd "\$GIT_PROJECT_PATH" | |
| (git add . && git commit -am "Online change") 1>&2 | |
| (>&2 echo "====== Now let's do the clone/pull =====") | |
| cd ~/ | |
| /usr/bin/git-upload-pack "\$@" | |
| EOF | |
| )" | |
| write_hook git-receive-pack "$(cat <<EOF | |
| #!/usr/bin/env bash | |
| GIT_PROJECT_PATH="\${GIT_PROJECT_PATH:-$GIT_PROJECT_PATH}" | |
| (>&2 echo "====== Let's first commit if needed =====") | |
| cd "\$GIT_PROJECT_PATH" | |
| (git add . && git commit -am "Online change") 1>&2 | |
| (>&2 echo "====== Now let's do the push =====") | |
| cd ~/ | |
| /usr/bin/git-receive-pack "\$@" | |
| (>&2 echo "====== Push finished, let's reset on server =====") | |
| cd "\$GIT_PROJECT_PATH" | |
| git reset --hard HEAD 1>&2 | |
| EOF | |
| )" | |
| ################# | |
| # set up git repo | |
| error_conflicting_git_config() { | |
| cat <<EOF >&2 | |
| cocalc-setup-git-bridge: warning: conflicting git config. Please ensure the following settings: | |
| $gitconfig receive.denyCurrentBranch = ignore # necessary for git push to work | |
| # some safety/security settings | |
| $gitconfig receive.denyDeleteCurrent = true | |
| $gitconfig receive.denyNonFastForwards = true | |
| $gitconfig receive.denyDeletes = true | |
| EOF | |
| exit 1 | |
| } | |
| gitconfig_try_set() { | |
| key="$1" | |
| valueNew="$2" | |
| valueOld="$($gitconfig --get "$key")" | |
| if [ $? == 0 ]; then | |
| if [ "$valueOld" != "$valueNew" ]; then | |
| error_conflicting_git_config | |
| fi | |
| else | |
| echo "setting $gitconfig '$key' '$valueNew'" | |
| $gitconfig "$key" "$valueNew" | |
| fi | |
| } | |
| gitconfig='git config --local' | |
| cd | |
| cd "$GIT_PROJECT_PATH" | |
| git_new=false | |
| if [ ! -d .git ]; then | |
| git_new=true | |
| git init | |
| fi | |
| # set user.{email,name}, if unset | |
| for key in user.{email,name}; do | |
| $gitconfig --get $key >/dev/null || $gitconfig $key cocalc | |
| done | |
| # allow pushing to checked-out branch | |
| gitconfig_try_set receive.denyCurrentBranch ignore | |
| # some safety/security measures against accidental destruction | |
| for key in receive.{denyDeleteCurrent,denyNonFastForwards,denyDeletes}; do | |
| gitconfig_try_set "$key" true | |
| done | |
| # set up .gitignore | |
| cat <<'EOF' >> .gitignore | |
| /build # if you want to use a build dir in the repo, which won't be deleted on container restart | |
| build/ | |
| *.pdf # comment out if you want to sync pdf built by cocalc | |
| *.synctex.gz | |
| *.syncdb | |
| *.sage-chat | |
| EOF | |
| ###################################### | |
| # instructions for local ssh+git setup | |
| SSH_USER="${COCALC_PROJECT_ID//-/}" | |
| cat <<EOF | |
| Git-bridge config files are set up. To complete configuration, add | |
| "PATH": "/home/user/bin", | |
| to the 'Custom Environment Variables' in the project settings. | |
| Then, you can setup an ssh key, e.g. with | |
| ssh-keygen -t ed25519 | |
| and copy the public key into your cocalc profile or the project settings. | |
| The default key location is ~/.ssh/id_<keytype>.pub, e.g. ~/.ssh/id_ed25519.pub. | |
| Then, clone this to your local git repo using | |
| git clone [email protected]:$GIT_PROJECT_PATH [<target directory>] | |
| or, in your local git repo, add the cocalc project as a git remote, e.g. as 'origin', using | |
| git remote add origin [email protected]:$GIT_PROJECT_PATH | |
| git pull --rebase | |
| git push | |
| Now, you can also ssh into the project with the command | |
| ssh "\$(git remote get-url $* | sed 's/\(@[^:]\+\)\(:.*\)\?\$/\1/g')" | |
| The cocalc project must be running in order to connect using git/ssh. | |
| You can start the project with a button in the cocalc console, in the project settings, | |
| or via the api as folows: | |
| First, set up an api key in the project settings and store it in the file 'cocalc_api_key'. | |
| Then, you can start the project using | |
| regex='^([a-z0-9]{8})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]+)@ssh.cocalc.com.*\$' | |
| project_id="\$(git remote get-url cocalc | sed -E s/"\$regex"/'\\1-\\2-\\3-\\4-\\5'/)" | |
| curl -u \$(cat cocalc_api_key): -d bash=true -d command=true -d project_id="\$project_id" \ | |
| https://cocalc.com/api/v1/project_exec | |
| WARNING: | |
| 1. Do not store a user key in cocalc_api_key, only a project key. Otherwise, when you sync | |
| this file via git, everyone with access to the repo would have access to your user and all your projects. | |
| 2. Watch out if you share the git repo outside its cocalc project: Whoever knows to the api key | |
| can modify the cocalc project and add/remove collaborators. | |
| EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment