From 1e5f77ffd134cf69245fb7b3151621f274606ef6 Mon Sep 17 00:00:00 2001
From: Sven-Hendrik Haase <svenstaro@gmail.com>
Date: Sun, 19 Jun 2016 20:08:37 +0200
Subject: [PATCH] dbscripts: Add svntogit

---
 playbooks/orion.yml                         |  2 +-
 roles/dbscripts/files/arch-svntogit.service |  7 ++
 roles/dbscripts/files/arch-svntogit.timer   |  9 ++
 roles/dbscripts/files/update-repos.sh       | 97 +++++++++++++++++++++
 roles/dbscripts/tasks/main.yml              | 61 +++++++++++++
 5 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 roles/dbscripts/files/arch-svntogit.service
 create mode 100644 roles/dbscripts/files/arch-svntogit.timer
 create mode 100644 roles/dbscripts/files/update-repos.sh

diff --git a/playbooks/orion.yml b/playbooks/orion.yml
index 952160a13..38a51cdbd 100644
--- a/playbooks/orion.yml
+++ b/playbooks/orion.yml
@@ -13,6 +13,6 @@
     - { role: postfix, tags: ['mail'] }
     - { role: archusers, tags: ['archusers'] }
     - { role: nginx, tags: ["nginx"] }
-    - { role: dbscripts, repos_domain: "repos.archlinux.org", tags: ['dbscripts', 'archusers'] }
+    - { role: dbscripts, repos_domain: "repos.archlinux.org", svntogit_repos: "/srv/svntogit/repos", tags: ['dbscripts', 'archusers'] }
     - { role: sudo, tags: ['sudo', 'archusers'] }
     - { role: archweb, archweb_home: "/srv/http/archweb", tags: ['archweb'] }
diff --git a/roles/dbscripts/files/arch-svntogit.service b/roles/dbscripts/files/arch-svntogit.service
new file mode 100644
index 000000000..d1559cdc6
--- /dev/null
+++ b/roles/dbscripts/files/arch-svntogit.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=arch-svntogit
+
+[Service]
+Type=oneshot
+User=svntogit
+ExecStart=/srv/svntogit/update-repos.sh
diff --git a/roles/dbscripts/files/arch-svntogit.timer b/roles/dbscripts/files/arch-svntogit.timer
new file mode 100644
index 000000000..c4842107c
--- /dev/null
+++ b/roles/dbscripts/files/arch-svntogit.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=arch-svntogit
+
+[Timer]
+OnBootSec=3min
+OnUnitActiveSec=5min
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/dbscripts/files/update-repos.sh b/roles/dbscripts/files/update-repos.sh
new file mode 100644
index 000000000..d089d42c8
--- /dev/null
+++ b/roles/dbscripts/files/update-repos.sh
@@ -0,0 +1,97 @@
+#!/bin/bash -eC
+
+REPO_HOME=/srv/svntogit/repos
+REPOS=(packages community)
+REMOTE=public
+LOCKFILE="$0.lock"
+
+update_pkg() {
+	local pkg=$1
+
+	if git show master:$pkg &>/dev/null; then
+		if ! git show-ref -q packages/$pkg; then
+			# Added package; create package branch
+			git branch packages/$pkg master
+			git filter-branch -f --subdirectory-filter $pkg packages/$pkg \
+				>/dev/null
+		else
+			# Updated package; apply changes to package branch
+			git checkout -q packages/$pkg
+			git format-patch -k --stdout last-commit-processed..master -- $pkg |
+				git am -k -p2 --keep-cr --committer-date-is-author-date \
+					&>/dev/null
+		fi
+	else
+		# Deleted package; destroy the branch and stop processing this package
+		git branch -D packages/$pkg &>/dev/null || true
+		git push -q --delete $REMOTE packages/$pkg &>/dev/null || true
+		return 0
+	fi
+}
+
+# Rather simple locking mechanism
+echo $$ >"$LOCKFILE"
+
+for repo in ${REPOS[@]}; do
+	echo "==> Updating '$repo' Git repository on $(date -u)"
+
+	pushd "$REPO_HOME/$repo" >/dev/null
+
+	# Make sure we have a last-commit-processed tag to work from
+	if ! git show-ref -q last-commit-processed; then
+		echo "==> ERR: Couldn't update '$repo' Git repository;" \
+			"missing last-commit-processed tag" >&2
+		# Skip to the next repo
+		continue
+	fi
+
+	# Make sure we're on the master branch
+	git checkout -q master
+
+	echo '  -> Fetching changes from SVN'
+	if ! git svn rebase &>/dev/null; then
+		echo '    > git svn rebase command failed; skipping to next repository'
+		echo "==> Aborted updating '$repo' on $(date -u)"
+		echo
+		popd >/dev/null
+		continue
+	fi
+
+	echo '  -> Updating package branches'
+	pkgs=($(git diff --name-only last-commit-processed.. | cut -d'/' -f1 |
+		uniq))
+	pkg_count=${#pkgs[@]}
+
+	if ((pkg_count)); then
+		# Update each package branch
+		for pkg in ${pkgs[@]}; do
+			echo "    > Updating package branch for '$pkg'"
+			update_pkg $pkg
+		done
+
+		# Return to the master branch
+		git checkout -q master
+
+		echo "  -> Updated $pkg_count package branches"
+
+		echo '  -> Updating public Git repository'
+		if ! git push -q --all $REMOTE &>/dev/null; then
+			echo '    > git push command failed'
+		fi
+	else
+		echo '    > No updates found'
+	fi
+
+	echo '  -> Tagging last commit processed'
+	git tag -f last-commit-processed >/dev/null
+
+	popd >/dev/null
+
+	echo "==> Finished updating '$repo' on $(date -u)"
+	echo
+done
+
+# Remove lock
+rm "$LOCKFILE"
+
+# vim:set ts=4 sw=4 noet:
diff --git a/roles/dbscripts/tasks/main.yml b/roles/dbscripts/tasks/main.yml
index b6ccc4c55..188f09773 100644
--- a/roles/dbscripts/tasks/main.yml
+++ b/roles/dbscripts/tasks/main.yml
@@ -164,6 +164,62 @@
 - name: install svnlog
   copy: src=svnlog dest=/usr/local/bin/svnlog owner=root group=root mode=755
 
+- name: add arch-svntogit user
+  user: name=svntogit shell=/sbin/nologin home=/srv/svntogit generate_ssh_key=yes ssh_key_bits=4096
+
+- name: configure svntogit git user name
+  command: git config --global user.name = 'svntogit'
+  become: yes
+  become_user: svntogit
+
+- name: configure svntogit git user email
+  command: git config --global user.name = 'svntogit@repos.archlinux.org'
+  become: yes
+  become_user: svntogit
+
+- name: template arch-svntogit
+  copy: src=update-repos.sh dest=/srv/svntogit/update-repos.sh owner=root group=root mode=755
+
+- name: create svntogit repos subdir
+  file: path="/srv/svntogit/repos" state=directory owner=svntogit group=svntogit mode=0775
+
+- name: clone git-svn repos
+  command: git svn clone file:///srv/repos/svn-{{ item }}/svn /srv/svntogit/repos/{{ item }} creates=/srv/svntogit/repos/{{ item }}
+  with_items:
+    - community
+    - packages
+  become: yes
+  become_user: svntogit
+
+- name: add svntogit public remotes
+  command: git remote add public ssh://git.archlinux.org/srv/git/svntogit/{{ item }}.git chdir=/srv/svntogit/repos/{{ item }}
+  with_items:
+    - community
+    - packages
+  become: yes
+  become_user: svntogit
+  ignore_errors: yes
+
+  # The following command also serves as a way to get the data the first time the repo is set up
+- name: configure svntogit pull upstream branch
+  command: git pull public master chdir=/srv/svntogit/repos/{{ item }}
+  with_items:
+    - community
+    - packages
+  become: yes
+  become_user: svntogit
+
+- name: configure svntogit push upstream branch
+  command: git push -u public master chdir=/srv/svntogit/repos/{{ item }}
+  with_items:
+    - community
+    - packages
+  become: yes
+  become_user: svntogit
+
+- name: fix svntogit home permissions
+  file: path="/srv/svntogit" state=directory owner=svntogit group=svntogit mode=0775
+
 - name: start and enable rsync
   service: name=rsyncd.socket enabled=yes state=started
 
@@ -191,6 +247,10 @@
     - lastsync.service
     - gen_rsyncd.timer
     - gen_rsyncd.service
+    - arch-svntogit.timer
+    - arch-svntogit.service
+  notify:
+    - daemon reload
 
 - name: activate systemd timers
   service: name={{ item }} enabled=yes state=started
@@ -201,3 +261,4 @@
     - integrity-check.timer
     - lastsync.timer
     - gen_rsyncd.timer
+    - arch-svntogit.timer
-- 
GitLab