diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | Makefile | 67 | ||||
-rwxr-xr-x | gitolite-sync | 70 | ||||
-rw-r--r-- | gitolite-sync.conf | 13 | ||||
-rw-r--r-- | gitolite-sync.in | 97 | ||||
-rw-r--r-- | gitolite-sync.service.in (renamed from gitolite-sync.service) | 4 | ||||
-rw-r--r-- | gitolite-sync.timer.in (renamed from gitolite-sync.timer) | 0 | ||||
-rw-r--r-- | man.commons.in | 14 |
8 files changed, 199 insertions, 72 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e68e611 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +gitolite-sync +gitolite-sync.service +gitolite-sync.timer +man.commons +*.common +*.1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..513dcbc --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +# +# gitolite-sync - synchronize git repositories (designed for gitolite +# managed ones) +# +# Copyright (c) 2013-2016 Erich Eckner <opensource at eckner dot net> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +DESTDIR = +ETCDIR = /etc +BINDIR = /usr/bin +GITUSER = gitolite +MANDIR = /usr/share/man + +VERSION = 0.0 + +all: man.commons \ + gitolite-sync gitolite-sync.1 \ + gitolite-sync.service gitolite-sync.timer + +%: %.in + sed " \ + s/#VERSION#/$(VERSION)/; \ + s@#BINDIR#@$(BINDIR)@; \ + s@#ETCDIR#@$(ETCDIR)@; \ + s@#GITUSER#@$(GITUSER)@; \ + s@#HELPTEXT#\(\s\+\)#@ --help \1display this help and exit\n --version\1display version and exit@; \ + " $< > $@ && \ + ( [[ "$@" = *.* ]] || chmod +x "$@" ) + +%.1: % man.commons + grep -v "^$<(" man.commons | sed '/^\[SEE ALSO]$$/{n;:a;N;/\[/b;s/\n/, /;ta;}' > "$<.common" && \ + help2man -o "$@" -N --include $<.common --no-discard-stderr "./$<" + +.PHONY: install dist clean + +install: all + install -D -m0755 -t $(DESTDIR)$(BINDIR) gitolite-sync + install -D -m0644 -t $(DESTDIR)$(LIBDIR)/systemd/system gitolite-sync.service gitolite-sync.timer + install -D -m0644 -t $(DESTDIR)$(MANDIR)/man1 gitolite-sync.1 + install -D -m0644 -t $(DESTDIR)$(ETCDIR) gitolite-sync.conf + +clean: + git clean -x -d -f + +dist: clean + git status --porcelain 2> /dev/null | grep -q "\S" && (git add .; git commit -m"neue Version: $(VERSION)") || true + ! git tag -d v$(VERSION) 2> /dev/null + git tag v$(VERSION) + git push + git push --tags + +# End of file diff --git a/gitolite-sync b/gitolite-sync deleted file mode 100755 index f25ba4e..0000000 --- a/gitolite-sync +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash - -home=$( - getent passwd gitolite \ - | cut -d: -f6 -) - -if [ -z "${home}" ] || [ ! -d "${home}" ]; then - >&2 echo 'cannot find user gitolite' - exit 1 -fi - -find "${home}/repositories" \ - -type d \ - -name '*.git' \ - -printf '%p\n' \ - -prune \ -| while read -r path; do - >&2 printf 'synchronizing "%s" ...\n' \ - "${path}" - remotes=$( - git -C "${path}" remote -v \ - | grep '[@.]eckner\.net:' \ - | awk '{print $1}' \ - | sort -u - ) - if [ -z "${remotes}" ]; then - >&2 printf 'Repository "%s" has no backup remotes.\n' \ - "${path}" - continue - fi - for remote in ${remotes}; do - git -C "${path}" fetch "${remote}" -p - done - branches=$( - git -C "${path}" branch --all \ - | sed ' - s,^.\sremotes/[^/[:space:]]\+/,, - t - d - ' - ) - if [ -n "$(git -C "${path}" tag -l)" ]; then - has_tags=true - else - has_tags=false - fi - if [ -z "${branches}" ] && ! ${has_tags}; then - >&2 printf 'Repository "%s" has no branches and no tags.\n' \ - "${path}" - continue - fi - for remote in ${remotes}; do - if ${has_tags}; then - git -C "${path}" push "${remote}" --tags - fi - if [ -z "${branches}" ]; then - continue - fi - for branch in ${branches}; do - if ! git -C "${path}" branch \ - | sed 's/^.\s//' \ - | grep -qxF "${branch}"; then - git -C "${path}" branch "${branch}" --track "${remote}/${branch}" - fi - git -C "${path}" pull --ff-only "${remote}" "${branch}" 2>/dev/null - git -C "${path}" push "${remote}" "${branch}" - done - done -done diff --git a/gitolite-sync.conf b/gitolite-sync.conf new file mode 100644 index 0000000..240ec0c --- /dev/null +++ b/gitolite-sync.conf @@ -0,0 +1,13 @@ +#!/bin/bash + +# this regex must match the to-be-synchronized remotes (or their url) +remote_regex='[@.]eckner\.net:' + +# these directories contain the to-be-synchronized repositories +repository_dirs=( + $( + getent passwd #GITUSER# \ + | cut -d: -f6 \ + | sed 's,$,/repositories,' + ) +) diff --git a/gitolite-sync.in b/gitolite-sync.in new file mode 100644 index 0000000..adc67bd --- /dev/null +++ b/gitolite-sync.in @@ -0,0 +1,97 @@ +#!/bin/bash + +if [ $# -eq 1 ]; then + if [ "$1" == "--help" ]; then + >&2 echo \ +'Usage: gitolite-sync [options] +Synchronize the configured git repositories. + +Options: +#HELPTEXT# #' + exit + elif [ "$1" == "--version" ]; then + echo '#VERSION#' + exit + fi +fi + +if [ $# -ne 0 ]; then + >&2 echo 'too many arguments' + exit 1 +fi + +. "#ETCDIR#/gitolite-sync.conf" + +if [ ${#repository_dirs[@]} -eq 0 ]; then + >&2 echo 'no repository_dirs defined' + exit 1 +fi + +for repository_dir in "${repository_dir[@]}"; do + if [ -z "${repository_dir}" ] || [ ! -d "${repository_dir}" ]; then + >&2 printf 'cannot find "%s"\n' \ + "${repository_dir}" + exit 1 + fi +done + +for repository_dir in "${repository_dir[@]}"; do + find "${repository_dir}" \ + -type d \ + -name '*.git' \ + -printf '%p\n' \ + -prune \ + | while read -r path; do + >&2 printf 'synchronizing "%s" ...\n' \ + "${path}" + remotes=$( + git -C "${path}" remote -v \ + | grep "${remote_regex}" \ + | awk '{print $1}' \ + | sort -u + ) + if [ -z "${remotes}" ]; then + >&2 printf 'Repository "%s" has no backup remotes.\n' \ + "${path}" + continue + fi + for remote in ${remotes}; do + git -C "${path}" fetch "${remote}" -p + done + branches=$( + git -C "${path}" branch --all \ + | sed ' + s,^.\sremotes/[^/[:space:]]\+/,, + t + d + ' + ) + if [ -n "$(git -C "${path}" tag -l)" ]; then + has_tags=true + else + has_tags=false + fi + if [ -z "${branches}" ] && ! ${has_tags}; then + >&2 printf 'Repository "%s" has no branches and no tags.\n' \ + "${path}" + continue + fi + for remote in ${remotes}; do + if ${has_tags}; then + git -C "${path}" push "${remote}" --tags + fi + if [ -z "${branches}" ]; then + continue + fi + for branch in ${branches}; do + if ! git -C "${path}" branch \ + | sed 's/^.\s//' \ + | grep -qxF "${branch}"; then + git -C "${path}" branch "${branch}" --track "${remote}/${branch}" + fi + git -C "${path}" pull --ff-only "${remote}" "${branch}" 2>/dev/null + git -C "${path}" push "${remote}" "${branch}" + done + done + done +done diff --git a/gitolite-sync.service b/gitolite-sync.service.in index f85eb43..32ca6cb 100644 --- a/gitolite-sync.service +++ b/gitolite-sync.service.in @@ -2,5 +2,5 @@ Description=synchronize gitolite repositories to and from backup location(s) [Service] -User=gitolite -ExecStart=/usr/bin/gitolite-sync +User=#GITUSER# +ExecStart=#BINDIR#/gitolite-sync diff --git a/gitolite-sync.timer b/gitolite-sync.timer.in index 4a4e9bc..4a4e9bc 100644 --- a/gitolite-sync.timer +++ b/gitolite-sync.timer.in diff --git a/man.commons.in b/man.commons.in new file mode 100644 index 0000000..c56a2f8 --- /dev/null +++ b/man.commons.in @@ -0,0 +1,14 @@ +[FILES] +#ETCDIR#/gitolite-sync.conf +[AUTHOR] +Erich Eckner <opensource at eckner dot net>. +[SEE ALSO] +gitolite-conf(1) +[CONFIG] +The configfile \fB#ETCDIR#/gitolite.conf\fP is a bash script, which defines the following variables: +.TP +.B "remote_regex" +regular expression for remotes that should be synchronized +.TP +.B "home_dirs" +array of directories to be synchronized by \fBgitolite-sync\fP |