From 8d2a3fd616842706aae8abcc7f2bd24ed1b5d14e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Filip=20Str=C3=B6mb=C3=A4ck?= <filip.stromback@liu.se>
Date: Wed, 30 Sep 2020 10:17:57 +0200
Subject: [PATCH] Added a script for keeping a Git repo updated.

It is not yet tested in contexts where it needs to be executed as another user.
---
 files/update_repo.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100755 files/update_repo.sh

diff --git a/files/update_repo.sh b/files/update_repo.sh
new file mode 100755
index 0000000..1742fb7
--- /dev/null
+++ b/files/update_repo.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+
+# Keep a Git repository updated. Optionally execute a command whenever it has been updated in order
+# to trigger further processing of some kind (e.g. restarting services).
+
+# The command is called as follows:
+# update_repo.sh <destination path> <source repo> <source branch>
+
+# If REPO_ON_UPDATE is set, then that command will be executed whenever the repo is created and/or
+# updated to a new revision. This can be used to trigger further processing of some sort, such as
+# compiling the contained source and/or restarting system services as appropriate.
+
+# This script is designed to be executed as a privillegied user so that the update command could do
+# privillegied operations. Thus, the git commands will be isolated to a user as described by
+# REPO_USER and REPO_GROUP, if they are is set. It is, of course, also possible to just run this
+# script as a regular user without setting REPO_USER.
+
+
+# Function that keeps the repo updated. Returns 0 if nothing was done, 100 if the repo was updated,
+# and something else on some kind of error. This function will be executed as the user indicated in
+# the environment variables.
+function update_repo() {
+    if [[ ! -d "$repo_path" ]]
+    then
+	# Does not exist. We need to checkout the repository.
+	git clone --single-branch --branch "$repo_branch" "$repo_source" "$repo_path" || exit 1
+	exit 100
+    else
+	# It does exist. Make sure it is updated.
+	cd "$repo_path"
+	old_sha=$(git rev-parse HEAD)
+	git fetch -f "$repo_source" "$repo_branch":remotes/origin/"$repo_branch" || exit 1
+	new_sha=$(git rev-parse remotes/origin/"$repo_branch")
+	if [[ "$old_sha" == "$new_sha" ]]
+	then
+	    # They are the same, we don't need to do anything.
+	    exit 0
+	else
+	    # They differ. Check out the new revision.
+	    git checkout -f "$new_sha" || exit 1
+	    git branch -f "$repo_branch" "$new_sha" || exit 1
+	    # This is not strictly necessary, but it makes it look like we have the correct branch
+	    # checked out. Good if someone inspects the repo at a later time.
+	    git checkout -f "$repo_branch" || exit 1
+	    exit 100
+	fi
+    fi
+}
+
+# Check for enough parameters.
+if [[ "$#" < 3 ]]
+then
+    echo "Not enough parameters."
+    echo "Usage: update_repo.sh <path> <source> <branch>"
+    exit 2
+fi
+
+# Setup variables for calling "update_repo"...
+repo_path="$1"
+repo_source="$2"
+repo_branch="$3"
+
+export repo_path repo_source repo_branch
+export -f update_repo
+
+if [[ -z "$REPO_USER" ]]
+then
+    # Just run it in a subshell
+    bash -c update_repo
+else
+    # Perhaps group was not supplied.
+    if [[ -z "$REPO_GROUP" ]]
+    then
+	REPO_GROUP="$REPO_USER"
+    fi
+    sudo --preserve-env=repo_path,repo_source,repo_branch,update_repo --set-home --user="$REPO_USER" --group="$REPO_GROUP" -- bash -c update_repo
+fi
+# Note: We cannot put any commands between the if-statement and here. We need the result code from
+# invoking bash, which is the last command in both the if- and else- branches.
+result="$?"
+if [[ $result == 0 ]]
+then
+    # All is well, nothing needed to be done.
+    exit 0
+elif [[ $result == 100 ]]
+then
+    # All is well, but we need to tell the environment that we updated the repo.
+    if [[ ! -z "$REPO_ON_UPDATE" ]]
+    then
+	# Run it if it is there.
+	$REPO_ON_UPDATE
+    fi
+    exit 0
+else
+    # Something went awry, forward the exit code.
+    exit $result
+fi
-- 
GitLab