From dc9bcb812ae1331b2bcdcb951252459d674f579b Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Tue, 28 Aug 2012 10:03:48 -0600 Subject: [PATCH] First commit --- git-overview | 145 +++++++++++++++++++++++++++++++++++++++++++++++ git-push-public | 28 +++++++++ git_backup | 51 +++++++++++++++++ push-public | 8 +++ repo-push-public | 10 ++++ server-gc | 55 ++++++++++++++++++ update-mirror | 103 +++++++++++++++++++++++++++++++++ 7 files changed, 400 insertions(+) create mode 100755 git-overview create mode 100755 git-push-public create mode 100755 git_backup create mode 100755 push-public create mode 100755 repo-push-public create mode 100755 server-gc create mode 100755 update-mirror diff --git a/git-overview b/git-overview new file mode 100755 index 0000000..7012705 --- /dev/null +++ b/git-overview @@ -0,0 +1,145 @@ +#!/bin/bash +# git-overview +# +# Review a filesystem subtree for git repos and show their overall state. +# Runs on the current directory if no argument is provided + +usage() +{ + [ -n "$1" ] && echo "$1" >&2 + echo "usage: $0 [directory]" >&2 + exit 1 +} + +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + if [ -n "${__git_dir-}" ]; then + echo "$__git_dir" + elif [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# __git_ps1 accepts 0 or 1 arguments (i.e., format string) +# returns text to add to bash PS1 prompt (includes branch name) +__git_ps1 () +{ + local g="$(__gitdir)" + if [ -n "$g" ]; then + local r + local b + if [ -f "$g/rebase-merge/interactive" ]; then + r="|REBASE-i" + b="$(cat "$g/rebase-merge/head-name")" + elif [ -d "$g/rebase-merge" ]; then + r="|REBASE-m" + b="$(cat "$g/rebase-merge/head-name")" + else + if [ -d "$g/rebase-apply" ]; then + if [ -f "$g/rebase-apply/rebasing" ]; then + r="|REBASE" + elif [ -f "$g/rebase-apply/applying" ]; then + r="|AM" + else + r="|AM/REBASE" + fi + elif [ -f "$g/MERGE_HEAD" ]; then + r="|MERGING" + elif [ -f "$g/BISECT_LOG" ]; then + r="|BISECTING" + fi + + b="$(git symbolic-ref HEAD 2>/dev/null)" || { + + b="$( + case "${GIT_PS1_DESCRIBE_STYLE-}" in + (contains) + git describe --contains HEAD ;; + (branch) + git describe --contains --all HEAD ;; + (describe) + git describe HEAD ;; + (* | default) + git describe --exact-match HEAD ;; + esac 2>/dev/null)" || + + b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." || + b="unknown" + b="($b)" + } + fi + + local w + local i + local s + local u + local c + + if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then + if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then + c="BARE:" + else + b="GIT_DIR!" + fi + elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then + if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then + git diff --no-ext-diff --ignore-submodules \ + --quiet --exit-code || w="*" + if git rev-parse --quiet --verify HEAD >/dev/null; then + git diff-index --cached --quiet \ + --ignore-submodules HEAD -- || i="+" + else + i="#" + fi + fi + fi + if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then + git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" + fi + + if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then + if [ -n "$(git ls-files --others --exclude-standard)" ]; then + u="%" + fi + fi + fi + + if [ -n "${1-}" ]; then + printf "$1" "$c${b##refs/heads/}$w$i$s$u$r" + else + printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r" + fi + fi +} + +# MAIN + +if [ $# -eq 1 ]; then + cd "$1" || usage "Bad directory" +fi + +( +for path in $(find . -maxdepth 3 -name .git -type d); do + repo="${path/\/.git}" + ( + cd $repo + echo $repo: $(__git_ps1) + for remote in $(git remote show); do + echo " $remote:" + git remote show $remote | grep "pushes to" + done + echo + ) +done +) 2>&1 diff --git a/git-push-public b/git-push-public new file mode 100755 index 0000000..3799985 --- /dev/null +++ b/git-push-public @@ -0,0 +1,28 @@ +#!/bin/bash +# git-push-public +# +# Push changes from local git repositories marked as public, via the +# git-daemon-export-ok flag, to the public server. + +LOCALBASE=/var/lib/git +PUBLICBASE=/var/cache/git +PUBLICSERVER="$1" +[ -z "$PUBLICSERVER" ] && PUBLICSERVER=oss.titaniummirror.com + +echo "Updating git repos on server $PUBLICSERVER" +cd $LOCALBASE +for path in $(find . -name git-daemon-export-ok); do + repo="${path/\/git-daemon-export-ok/}" + repo="${repo/.\//}" + echo "Repository $repo" + if ! ssh $PUBLICSERVER test -d $PUBLICBASE/$repo ; then + # Repo does not exist on public server, so create it + echo "Creating repository $repo on remote" + ssh $PUBLICSERVER git --git-dir=$PUBLICBASE/$repo init --bare + ssh $PUBLICSERVER touch $PUBLICBASE/$repo/git-daemon-export-ok + scp $repo/description $PUBLICSERVER:$PUBLICBASE/$repo/ + ssh $PUBLICSERVER "echo \"git://$PUBLICSERVER/$repo\" \ + > $PUBLICBASE/$repo/cloneurl" + fi + git --git-dir=$repo push --mirror $PUBLICSERVER:$PUBLICBASE/$repo +done diff --git a/git_backup b/git_backup new file mode 100755 index 0000000..3a67dac --- /dev/null +++ b/git_backup @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Backup git DB's to sporian. This is an alternate facility to SVN, for +# the paranoid like me. Also allows me to keep temp branches. + + +# Ensure we have an ssh key on SVHOST +SVHOST=iweb.sporian.com +SVDIR=TMI/git +SVURL=$SVHOST:$SVDIR + +rsync_proj() +{ + proj=$1 + echo "Project $proj [via rsync]" + ( + # SVHOST may not have git + ssh $SVHOST mkdir -p $SVDIR/${proj}.git + rsync -avz --delete $proj/.git/ $SVURL/${proj}.git/ + ) +} + +git_proj() +{ + proj=$1 + echo "Project $proj [via git]" + ( + # Easier when SVHOST has git + cd $proj + ssh $SVHOST test -d $SVDIR/${proj}.git || \ + ssh $SVHOST git --git-dir $SVDIR/${proj}.git init --bare --shared=true + git push --mirror "$SVURL/${proj}.git" + ) +} + +#cd ~/workspace/sporian +if [ -n "$1" ]; then + if [ -d "$1" -a -d "$1/.git" ]; then + #rsync_proj $1 + git_proj $1 + else + echo "$0: skip ~/workspace/sporian/$1; not a git project" >&2 + exit 1 + fi +else + for i in $(find . -name .git -type d 2>/dev/null); do + #rsync_proj $(basename $(dirname $i)) + git_proj $(basename $(dirname $i)) + done +fi +exit 0 diff --git a/push-public b/push-public new file mode 100755 index 0000000..5686f37 --- /dev/null +++ b/push-public @@ -0,0 +1,8 @@ +#!/bin/bash +# push-public +# +# Push changes to everything local that can be exported to the public +# web server. + +git-push-public $* +repo-push-public $* diff --git a/repo-push-public b/repo-push-public new file mode 100755 index 0000000..d0251dc --- /dev/null +++ b/repo-push-public @@ -0,0 +1,10 @@ +#!/bin/bash +# +# Push changes to the local TMI repo to the public repo. We really should be +# using launchpad to host the public version of the TMI repo. + +PUBLICSERVER="$1" +[ -z "$PUBLICSERVER" ] && PUBLICSERVER=oss.titaniummirror.com + +echo "Updating APT repo on $PUBLICSERVER" +rsync -avz --delete /var/local/aptrepo/ $PUBLICSERVER:/var/local/aptrepo/ diff --git a/server-gc b/server-gc new file mode 100755 index 0000000..b24ef89 --- /dev/null +++ b/server-gc @@ -0,0 +1,55 @@ +#!/bin/sh +# +# server-gc -- Run git-gc on each git repository found within the provided +# filesystem directory tree. Useful for shared on-server repos that don't +# automatically do gc operations. This script was first posted at +# http://groups.google.com/group/repo-discuss/web/repository-repacking +# +# NOTE: THIS UTILITY DOES NOT REALLY APPEAR TO BE NEEDED. + +if [ $(whoami) != "root" ]; then + echo "usage: $0 must be ran as root" >&2 + exit 1 +fi + +TOP=$1 +if [ ! -d "$TOP" ]; then + echo "usage: $0 >" >&2 + exit 1 +fi + +cd $TOP +for p in $(find . -type d -name \*.git | sed 's,^./,,') +do + d=$TOP/$p + echo + echo "*** Repository $d ***" + + git --git-dir=$d config repack.usedeltabaseoffset true + git --git-dir=$d config pack.compression 9 + git --git-dir=$d config pack.indexversion 2 + + git --git-dir=$d config gc.autopacklimit 4 + git --git-dir=$d config gc.packrefs true + git --git-dir=$d config gc.reflogexpire never + git --git-dir=$d config gc.reflogexpireunreachable never + + case $p in + kernel/lk.git) + : use defaults + ;; + kernel/*) + git --git-dir=$d config pack.threads 6 + git --git-dir=$d config pack.window 250 + git --git-dir=$d config pack.depth 50 + ;; + esac + + rm -rf $d/logs/refs/changes 2>/dev/null + + git --git-dir=$d gc --auto --aggressive --prune || break + + (find $d/refs/changes -type d | xargs rmdir; + find $d/refs/changes -type d | xargs rmdir + ) 2>/dev/null +done diff --git a/update-mirror b/update-mirror new file mode 100755 index 0000000..b68e8c1 --- /dev/null +++ b/update-mirror @@ -0,0 +1,103 @@ +#!/bin/bash +# +# Usage: update-mirror +# +# Derived from girocco's taskd/clone.sh script. See +# http://repo.or.cz/w/girocco.git + +set -e + +cfg_gitweburl=http://$(hostname)/gitweb +cfg_reporoot=/var/lib/git/mirrors + +url=$1 +projdir=$2 + +proj="${projdir%.git}" + +echo "[$proj] update mirror" +echo "[$proj] $url -> $projdir" + +if [ ! -d "$cfg_reporoot/$projdir" ]; then + echo "[$proj] $projdir is a new project" + mkdir -p "$cfg_reporoot/$projdir" + touch "$cfg_reporoot/$projdir/.new_clone" +fi +touch "$cfg_reporoot/$projdir/.clone_in_progress" + +cd "$cfg_reporoot/$projdir" +trap "echo \"[$proj] clone failed\"; touch .clone_failed" EXIT + +mail="sysadmin" + +# Initial mirror +echo "[$proj] mirroring..." +case "$url" in + svn://* | svn+http://* | svn+https://*) + # we just remove svn+ here, so svn+http://... becomes http://... + svnurl="${url#svn+}" + if [ -f "$cfg_reporoot/$projdir/.new_clone" ]; then + echo "[$proj] initial git-svn setup" + git --git-dir . --bare init + git --git-dir . svn init -s --prefix=svn-origin/ "$svnurl" + # have git-svn store branches under svn-origin/heads/* not svn-origin/* + # FIXME: may need to do similar when new branches are added + git --git-dir . config svn-remote.svn.branches \ + "$(git config --get svn-remote.svn.branches | \ + sed 's|:refs/remotes/svn-origin/\*$|:refs/remotes/svn-origin/heads/*|')" + git --git-dir . svn fetch + # Neat Trick suggested by Miklos Vajna + git --git-dir . config remote.origin.url . + git --git-dir . config remote.origin.fetch \ + '+refs/remotes/svn-origin/heads/*:refs/heads/*' + git --git-dir . config --add remote.origin.fetch \ + '+refs/remotes/svn-origin/trunk:refs/heads/master' + git --git-dir . config --add remote.origin.fetch \ + '+refs/remotes/svn-origin/tags/*:refs/tags/*' + rm -f "$cfg_reporoot/$projdir/.new_clone" + fi + echo "[$proj] fetching new commits from upstream" + git --git-dir . svn fetch + git --git-dir . fetch + ;; + + darcs://*) + echo "[$proj] darcs mirrors not yet supported" + exit 1 + httpurl="${url/darcs:\/\//http://}" + /usr/bin/darcs-fast-export --export-marks=$(pwd)/dfe-marks "$httpurl" | \ + git fast-import --export-marks=$(pwd)/gfi-marks + # This is here because by default only the exit code of + # git fast-import is checked + [ ${PIPESTATUS[0]} = 0 -a ${PIPESTATUS[1]} = 0 ] + ;; + + bzr://*) + echo "[$proj] bazaar mirrors not yet supported" + exit 1 + # we just remove bzr:// here, a typical bzr url is just + # "lp:foo" + bzrurl="${url#bzr://}" + bzr fast-export --export-marks=$(pwd)/bfe-marks "$bzrurl" | \ + git fast-import --export-marks=$(pwd)/gfi-marks + [ ${PIPESTATUS[0]} = 0 -a ${PIPESTATUS[1]} = 0 ] + ;; + + *) + if [ -f "$cfg_reporoot/$projdir/.new_clone" ]; then + echo "[$proj] initial git setup" + git --git-dir . --bare init + git --git-dir . remote rm origin >/dev/null 2>&1 || : + git --git-dir . remote add --mirror origin "$url" + fi + echo "[$proj] fetching new commits from upstream" + git --git-dir . remote update + git --git-dir . remote prune origin + ;; +esac + +# The rest +git update-server-info +trap "" EXIT +rm .clone_in_progress +echo "[$proj] clone updated. See $cfg_gitweburl/?p=mirrors/$projdir;a=summary" -- 2.39.2