monotone-commits-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-commits-diffs] net.venge.monotone.contrib.usher: e7277c425674


From: code
Subject: [Monotone-commits-diffs] net.venge.monotone.contrib.usher: e7277c425674dd747b3f4b809c56af2f488971c4
Date: Wed, 19 Jan 2011 13:57:27 GMT

revision:            e7277c425674dd747b3f4b809c56af2f488971c4
date:                2011-01-19T13:57:18
author:              Timothy Brownawell  <address@hidden>
branch:              net.venge.monotone.contrib.usher
changelog:
merge of '200716ad68df60ea4de9b92bf20d8acd1cf20283'
     and '7502a593e822d0ec5541e2682d39c9919a8d8edb'

manifest:
format_version "1"

new_manifest [2e37fafd67df2478ee31e5cc44ecb89f76286c7a]

old_revision [200716ad68df60ea4de9b92bf20d8acd1cf20283]

patch "utils/usherctl"
 from [f6f4d53eb56bdec130b464c53a5c14060c248dec]
   to [b29d51898d66a04f4808afa79dcac9ea24fc0279]

old_revision [7502a593e822d0ec5541e2682d39c9919a8d8edb]

add_file "release-checklist.txt"
 content [305136c17d554f0b16fdab39873c5814cc64691a]

patch "NEWS"
 from [a9b8cb5b3dc0ec686519bbb81dc1058d30fb1099]
   to [41f6acc0681f23e164e7d8dc6be0738de13a8bf1]

patch "README"
 from [b968eb93f8b8ce88d822e9ddc52b563f1742a147]
   to [84610efd11606729230d94fb905e5e4695328c7b]

patch "src/channel.cc"
 from [7e6b6bbae6a84041ec840bedf5816bd6e116e5ea]
   to [28d584b7185308aeab9297b3c9ceae03718a9e65]

patch "src/channel.hh"
 from [3a97687c17a68c983872de2792defd9e48028168]
   to [21231cc383b16935ac33a349718e5aa775341c45]

patch "src/server.hh"
 from [dd153b5671f0b9560be8b817849731419e5b8fe4]
   to [6a57214c24d5c35c705276dcae8415dfcabf6c6e]

patch "src/server_manager.cc"
 from [0abe47e13dd931c522aa1a7fb828502d63531a6e]
   to [f4a5b6fe2d917f24ce56c133ee347b9b3e91e50b]

patch "src/server_manager.hh"
 from [fc8ad29b28f82cae3b26955995afdad8f1276a5a]
   to [1d1f3a16329bdf11b69fb7593d048d95c65edc8d]

patch "src/sock.hh"
 from [0917e736d673fa6d15fcefea8f1f0e16a63b9bc2]
   to [b077f32cc61674e13b9c3bc138c924c41b23ceb1]
============================================================
--- utils/usherctl	f6f4d53eb56bdec130b464c53a5c14060c248dec
+++ utils/usherctl	b29d51898d66a04f4808afa79dcac9ea24fc0279
@@ -21,6 +21,8 @@ MTN=/usr/bin/mtn
 #			(default: $USHER_CONFDIR/global.conf)
 # USHER_CONFD		Directory for project specific configuration files.
 #			(default: $USHER_CONFDIR/conf.d)
+# USHER_SKEL		Directory for project skeleton files.
+#			(default: $USHER_CONFDIR/skel)
 # USHER_PIDFILE		Usher PID file.
 #			(default: /var/run/usher.pid)
 # USHER_LOGDIR		Usher log directory.
@@ -66,6 +68,7 @@ USHER_CONFD=${USHER_CONFD:-"$USHER_CONFD
 USHER_CONF=${USHER_CONF:-"$USHER_CONFDIR/usher.conf"}
 USHER_GLOBALCONF=${USHER_GLOBALCONF:-"$USHER_CONFDIR/global.conf"}
 USHER_CONFD=${USHER_CONFD:-"$USHER_CONFDIR/conf.d"}
+USHER_SKEL=${USHER_SKEL:-"$USHER_CONFDIR/skel"}
 USHER_PIDFILE=${USHER_PIDFILE:-/var/run/usher.pid}
 USHER_LOGDIR=${USHER_LOGDIR:-/var/log/usher}
 USHER_PROJECTDIR=${USHER_PROJECTDIR:-/var/lib/usher/projects}
@@ -85,34 +88,49 @@ _read_pid_file () {
     fi
 }
 
-status () {
+status0 () {
     if [ -z $USHER_SYSTEM_STARTUP ]; then
 	pid=`_read_pid_file`
 	if [ -n "$pid" ]; then
+	    echo "$pid"
 	    if kill -0 $pid 2>/dev/null; then
-		echo "The usher process is up and running: $pid"
 		return 0
 	    else
-		echo "The usher process is down, but there's a PID file."
 		return 1
 	    fi
 	else
-	    echo "The usher process is down."
 	    return 2
 	fi
     else
 	/etc/init.d/usher status
     fi
 }
+status () {
+    pid=`status0`
+    local save_rc=$?
+    case $save_rc in
+	0 )
+	    if [ -z "$pid" ]; then
+		echo "The usher process is up and running"
+	    else
+		echo "The usher process is up and running: $pid"
+	    fi
+	    ;;
+	1 )
+	    echo "The usher process is down, but there's a PID file."
+	    ;;
+	2 )
+	    echo "The usher process is down."
+	    ;;
+    esac
+    return $save_rc
+}
 
 start () {
     if [ -z $USHER_SYSTEM_STARTUP ]; then
-	pid=`_read_pid_file`
-	if [ -n "$pid" ]; then
-	    if kill -0 $pid 2>/dev/null; then
-		echo >&2 "Usher process already up: $pid"
-		exit 1
-	    fi
+	if pid=`status0`; then
+	    echo >&2 "Usher process already up: $pid"
+	    exit 1
 	fi
 	rm -f "$USHER_PIDFILE"
 	$USHER -p "$USHER_PIDFILE" "$USHER_CONF" \
@@ -124,8 +142,7 @@ stop () {
 
 stop () {
     if [ -z $USHER_SYSTEM_STARTUP ]; then
-	pid=`_read_pid_file`
-	if [ -n "$pid" ]; then
+	if pid=`status0`; then
 	    kill $pid
 	fi
     else
@@ -135,12 +152,11 @@ reload () {
 
 reload () {
     if [ -z $USHER_SYSTEM_STARTUP ]; then
-	pid=`_read_pid_file`
-	if [ -z "$pid" ]; then
+	if pid=`status0`; then
+	    kill -1 $pid
+	else
 	    echo >&2 "No usher process present."
 	    exit 1
-	else
-	    kill -1 $pid
 	fi
     else
 	/etc/init.d/usher reload
@@ -149,20 +165,15 @@ restart () {
 
 restart () {
     if [ -z $USHER_SYSTEM_STARTUP ]; then
-	stop && start
+	stop && sleep 1 && start
     else
 	/etc/init.d/usher restart
     fi
 }
 
 restart_if_started () {
-    if [ -z $USHER_SYSTEM_STARTUP ]; then
-	pid=`_read_pid_file`
-	if [ -n "$pid" ]; then
-	    restart
-	fi
-    elif /etc/init.c/usher status >/dev/null 2>/dev/null; then
-	/etc/init.d/usher restart
+    if pid=`status0`; then
+	restart
     fi
 }
 
@@ -196,6 +207,26 @@ rebuild () {
     ) > "$USHER_CONF"
     _maybe_set_file_owner "$USHER_CONF"
     chmod 640 "$USHER_CONF"
+
+    mkdir "$USHER_SKEL" 2> /dev/null
+    _maybe_set_file_owner "$USHER_SKEL"
+    chmod 750 "$USHER_SKEL"
+    cat "$THIS" | grep '^# -----BEGIN init:.*-----$' | \
+	sed -e 's/^# -----BEGIN init://' -e 's/-----$//' | while read f; do
+	d=`dirname "$f"`
+	if [ ! -d "$USHER_SKEL/$d" ]; then
+	    mkdir -p "$USHER_SKEL/$d"
+	    _maybe_set_file_owner "$USHER_SKEL/$d"
+	    chmod 750 "$USHER_CONF"
+	fi
+	ff="`echo "$f" | sed -e 's|/|\\\\/|g'`"
+	sed -e '1,/^# -----BEGIN init:'"$ff"'-----$/d' \
+	    -e '/^# -----END init:'"$ff"'-----$/,$d' \
+	    -e 's/^# //' \
+	    < "$THIS" > "$USHER_SKEL/$f"
+	_maybe_set_file_owner "$USHER_SKEL/$f"
+	chmod 640 "$USHER_SKEL/$f"
+    done
 }
 
 # $1	operation
@@ -204,7 +235,7 @@ rebuild () {
 # $4	pattern prefix
 # $5	type (remote local)
 # $6-	args
-writesrv () {
+writesrv0 () {
     op="$1"; shift
     name="$1"; shift
     host="$1"; shift
@@ -246,29 +277,39 @@ writesrv () {
     _maybe_set_file_owner "$USHER_CONFD/$name.conf"
     chmod 640 "$USHER_CONFD/$name.conf"
     rebuild
-    echo >&2 "Server '$name' $op, please reload usher to activate."
+    echo >&2 "Server '$name' $op."
 }
 
+writesrv () {
+    writesrv0 "$@"
+    echo >&2 "Please reload usher to activate."
+}
+
 # $1	server name
 # $2	host prefix
 # $3	pattern prefix
 # $4	type (remote local)
 # $5-	args
-addsrv () {
+addsrv0 () {
     if [ -f "$USHER_CONFD/$1.conf" ]; then
 	echo >&2 "There is already a server named '$1', not changing."
 	exit 1
     fi
 
-    writesrv added "$@"
+    writesrv0 added "$@"
 }
 
+addsrv () {
+    addsrv0 "$@"
+    echo >&2 "Please reload usher to activate."
+}
+
 # $1	server name
 # $2	host prefix
 # $3	pattern prefix
 # $4	type (remote local)
 # $5-	args
-modsrv () {
+modsrv0 () {
     name="$1"; shift
     ohost="$1"; host="$1"; shift
     opattern="$1"; pattern="$1"; shift
@@ -302,11 +343,16 @@ modsrv () {
 	esac
     done < "$USHER_CONFD/$name.conf"
     mv "$USHER_CONFD/$name.conf" "$USHER_CONFD/$name.conf~"
-    writesrv modified "$name" "$host" "$pattern" "$@"
+    writesrv0 modified "$name" "$host" "$pattern" "$@"
 }
 
+modsrv () {
+    modsrv0 "$@"
+    echo >&2 "Please reload usher to activate."
+}
+
 # $1	server name
-delsrv () {
+delsrv0 () {
     name="$1"
     
     if [ ! -f "$USHER_CONFD/$name.conf" ]; then
@@ -316,9 +362,50 @@ delsrv () {
 
     rm -f "$USHER_CONFD/$name.conf" "$USHER_CONFD/$name.conf~"
     rebuild
-    echo >&2 "Server '$name' deleted, please reload usher to activate."
+    echo >&2 "Server '$name' deleted."
 }
 
+delsrv () {
+    delsrv0 "$@"
+    echo >&2 "Please reload usher to activate."
+}
+
+# $1 name
+rebuild_permissions () {
+    confdir="$USHER_PROJECTDIR/$name"
+    aconfdir="$confdir/admin"
+    amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+    listenport=`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
+	cut -f2 -d'"' | cut -f2 -d:`
+
+    cp "$aconfdir/rakeys" "$confdir/remote-automate-permissions.new.$$"
+    cp "$aconfdir/rwkeys" "$confdir/write-permissions.new.$$"
+    patterns="`cat "$aconfdir/patterns" | sed -e '/^ *$/d'`"
+    if [ -z "$patterns" ]; then patterns="*"; fi
+    echo "$patterns" | while read p; do
+	echo "pattern \"$p\"";
+	if [ -f "$aconfdir/type.private" ]; then
+	    cat "$aconfdir/rokeys" "$aconfdir/rwkeys" | sort | uniq | \
+		sed -e 's/^/  allow "/' -e 's/$/"/'
+	else
+	    echo "  allow \"*\""
+	fi
+	echo
+    done > "$confdir/read-permissions.new.$$"
+
+    mv "$confdir/read-permissions.new.$$" "$confdir/read-permissions"
+    mv "$confdir/write-permissions.new.$$" "$confdir/write-permissions"
+    mv "$confdir/remote-automate-permissions.new.$$" \
+	"$confdir/remote-automate-permissions"
+
+    _maybe_set_file_owner "$confdir/read-permissions"
+    _maybe_set_file_owner "$confdir/write-permissions"
+    _maybe_set_file_owner "$confdir/remote-automate-permissions"
+    chmod 0640 "$confdir/read-permissions"
+    chmod 0640 "$confdir/write-permissions"
+    chmod 0640 "$confdir/remote-automate-permissions"
+}
+
 # $1 type
 # $2 name
 mkproject () {
@@ -331,6 +418,10 @@ mkproject () {
     fi
 
     confdir="$USHER_PROJECTDIR/$name"
+    aconfdir="$confdir/admin"
+
+
+    # Create protect project infrastructure
     set -e
     mkdir "$confdir"
     mkdir "$confdir/hooks.d"
@@ -339,6 +430,35 @@ mkproject () {
     _maybe_set_directory_owner "$confdir"
     chmod 0750 "$confdir"
 
+    # Create and protect admin infrastructure
+    set -e
+    mkdir "$aconfdir"
+    set +e
+
+    _maybe_set_directory_owner "$aconfdir"
+    chmod 700 "$aconfdir"
+
+
+    # --- Usher administration ---
+    amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+
+    # Generate admin key
+    (echo; echo) | eval $amtn genkey "\"$name-admin\"" > /dev/null 2> /dev/null
+    akid=`eval $amtn ls keys | grep "$name-admin\$" | tail -1 | cut -f1 -d' '`
+    _maybe_set_directory_owner "$aconfdir/keys"
+
+    # Add admin information
+    touch "$aconfdir/type.$type"	# A marker for the project type
+    touch "$aconfdir/patterns"		# The branch patterns handled by this
+					# project.  If none, "*" is assumed.
+    touch "$aconfdir/rokeys"		# r/o key identities, one per line.
+    touch "$aconfdir/rwkeys"		# r/w key identities, one per line.
+    touch "$aconfdir/rakeys"		# remote_automate permissions key
+					# identities, one per line.
+
+    # --- Project ---
+    mtn="$MTN -d \"$confdir/database.mtn\" --confdir \"$confdir\" --no-standard-rcfiles --ticker=dot --no-workspace"
+
     # Generate name and password for the server key
     skn="$name-server"
     skp=`dd if=/dev/random ibs=8 count=1 2>/dev/null | \
@@ -347,101 +467,63 @@ mkproject () {
     _maybe_set_file_owner "$confdir/passphrases"
     chmod 400 $confdir/passphrases
 
-    # Generate database
-    mtn="$MTN -d \"$confdir/database.mtn\" --confdir \"$confdir\" --no-standard-rcfiles --ticker=dot"
+    # Generate server database
     eval $mtn db init
     _maybe_set_file_owner "$confdir/database.mtn"
     chmod 0600 "$confdir/database.mtn"
 
-    # Generate key
+    # Generate server key
     (echo "$skp"; echo "$skp") | \
-	eval $mtn genkey "$skn" > /dev/null 2> /dev/null
+	eval $mtn genkey "\"$skn\"" > /dev/null 2> /dev/null
     skid=`eval $mtn ls keys | grep "$skn\$" | tail -1 | cut -f1 -d' '`
     _maybe_set_directory_owner "$confdir/keys"
 
-    sed -e '1,/^# -----BEGIN monotonerc-----$/d' \
-	-e '/^# -----END monotonerc-----$/,$d' \
-	-e 's/^# //' \
-	< "$THIS" > "$confdir/monotonerc"
-    _maybe_set_file_owner "$confdir/monotonerc"
-    chmod 0640 "$confdir/monotonerc"
+    # Generate server monotonerc and other scripts, from skeleton files
+    (
+	cd "$USHER_SKEL"
+	for x in both $type; do
+	    [ -d $x ] && find $x -type f
+	done
+    ) | while read f; do
+	section=`echo "$f" | sed -e 's|/.*$||'`
+	ff=`echo "$f" | sed -e 's|^'"$section"'/||'`
+	d=`dirname "$ff"`
+	b=`basename "$ff" .in`
+	if [ ! -d "$confdir/$d" ]; then
+	    mkdir -p "$confdir/$d"
+	    _maybe_set_file_owner "$confdir/$d"
+	    chmod 750 "$confdir/$d"
+	fi
+	if [ "$d/$b" = "$ff" ]; then
+	    ln -s "$USHER_SKEL/$f" "$confdir/$d/$b"
+	else
+	    sed -e "s|%adminkey%|$akid|g" \
+		< "$USHER_SKEL/$f" > "$confdir/$d/$b"
+	fi
+	_maybe_set_file_owner "$confdir/$d/$b"
+	chmod 0640 "$confdir/$d/$b"
+    done
 
-    aconfdir="$confdir/admin"
-    mkdir "$aconfdir"
-    _maybe_set_directory_owner "$aconfdir"
-    chmod 700 "$aconfdir"
+    # --- Finalise ---
 
-    amtn="$MTN -d \"$aconfdir/database.mtn\" --confdir \"$aconfdir\" --no-standard-rcfiles --ticker=dot"
-    eval $amtn db init
-    _maybe_set_file_owner "$aconfdir/database.mtn"
-    chmod 0600 "$aconfdir/database.mtn"
+    # bootstrap admin key into the project database
+    eval $amtn pubkey "\"$name-admin\"" | eval $mtn read 2> /dev/null
+    echo "$akid" > "$aconfdir/rakeys"
 
-    (echo; echo) | eval $amtn genkey "$name-admin" > /dev/null 2> /dev/null
-    akid=`eval $amtn ls keys | grep "$akn\$" | tail -1 | cut -f1 -d' '`
-    _maybe_set_directory_owner "$aconfdir/keys"
-
-    listenport=`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
-	cut -f2 -d'"' | cut -f2 -d:`
-
-    case $type in
-	public )
-	    (
-		echo 'pattern "*"'
-		echo '  allow "*"'
-	    ) > "$confdir/read-permissions"
-	    touch "$confdir/write-permissions"
-	    sed -e '1,/^# -----BEGIN pub:addclientkeys-----$/d' \
-		-e '/^# -----END pub:addclientkeys-----$/,$d' \
-		-e "s|%amtn%|$amtn|g" \
-		-e "s|%confdir%|$confdir|g" \
-		-e "s|%listenport%|$listenport|g" \
-		-e "s|%name%|$name|g" \
-		-e "s|%user%|$USHER_USER|g" \
-		-e "s|%group%|$USHER_GROUP|g" \
-		-e 's/^# //' \
-		< "$THIS" > "$confdir/addclientkeys"
-	    ;;
-	private )
-	    (
-		echo 'pattern "*"'
-	    ) > "$confdir/read-permissions"
-	    touch "$confdir/write-permissions"
-	    sed -e '1,/^# -----BEGIN priv:addclientkeys-----$/d' \
-		-e '/^# -----END priv:addclientkeys-----$/,$d' \
-		-e "s|%amtn%|$amtn|g" \
-		-e "s|%confdir%|$confdir|g" \
-		-e "s|%listenport%|$listenport|g" \
-		-e "s|%name%|$name|g" \
-		-e "s|%user%|$USHER_USER|g" \
-		-e "s|%group%|$USHER_GROUP|g" \
-		-e 's/^# //' \
-		< "$THIS" > "$confdir/addclientkeys"
-	    ;;
-    esac
-
-    _maybe_set_file_owner "$confdir/read-permissions"
-    _maybe_set_file_owner "$confdir/write-permissions"
-    _maybe_set_file_owner "$confdir/addclientkeys"
-    chmod 0640 $confdir/read-permissions
-    chmod 0640 $confdir/write-permissions
-    chmod 0600 $confdir/addclientkeys
-
-    # We need a quick bootstrap, otherwise addclientkeys won't work
-    eval $amtn pubkey "$name-admin" | eval $mtn read 2> /dev/null
-
-    addsrv "$name" "" "" \
+    # add project server
+    addsrv0 "$name" "" "" \
 	local "--confdir" "$confdir" "-d" "$confdir/database.mtn" \
 	"--no-standard-rcfiles" "--rcfile" "$confdir/monotonerc" \
-	"--timestamps" "--ticker=dot" 2>/dev/null
+	"--timestamps" "--ticker=dot"
+
     restart_if_started
 
-    _maybe_set_file_owner "$confdir/addclientkeys"
-    chmod 700 "$confdir/addclientkeys"
-    eval $amtn pubkey "$name-admin" | "$confdir/addclientkeys"
+    rebuild_permissions "$name"
 
     echo >&2 "$type project '$name' created."
 }
 
+# $1: name
 rmproject () {
     name="$1"; shift
 
@@ -450,12 +532,104 @@ rmproject () {
 	exit 1
     fi
 
-    delsrv "$name" 2>/dev/null
+    delsrv0 "$name"
     restart_if_started
     rm -rf "$USHER_PROJECTDIR/$name"
     echo >&2 "project '$name' removed."
 }
 
+# $1: name
+# $2: type
+# stdin: public key
+addprojectkey () {
+    name="$1"; shift
+    type="$1"; shift
+    key="`cat`"
+
+    if [ ! -e "$USHER_PROJECTDIR/$name" ]; then
+	echo >&2 "There is no project named '$name'."
+	exit 1
+    fi
+
+    confdir="$USHER_PROJECTDIR/$name"
+    aconfdir="$confdir/admin"
+    amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+    listenaddr=mtn://`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
+	cut -f2 -d'"' | sed -e 's|^0\.0\.0\.0:\(.*\)$|127.0.0.1:\1|'`/"$name"
+
+    # Send the public key to the project server
+    if ! eval $amtn --keydir "\"$aconfdir/keys\"" --key "$name-admin" \
+	automate remote --remote-stdio-host $listenaddr \
+	put_public_key "\"$key\"" 2> /tmp/mtn.$$.err; then
+	echo >&2 "Couldn't add public key to remote server $listenaddr"
+	echo >&2 "------------"
+	cat >&2 /tmp/mtn.$$.err
+	echo >&2 "------------"
+	exit 1
+    fi
+
+    # Figure out the key identity
+    eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" db init
+    echo "$key" | \
+	eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" read 2> /dev/null
+    keyid=`eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" ls keys | \
+	sed -e '/\[private keys\]/,$d' | grep '^[0-9a-f]' | fgrep -v '(*)' | \
+	cut -f1 -d' '`
+    rm -f "$aconfdir/throwaway.$$.mtn"
+
+    # Add the key identity to the appropriate key file
+    x=$type
+    case "$type" in
+	ro )
+	    echo "$aconfdir/rokeys"
+	    ;;
+	rw )
+	    echo "$aconfdir/rokeys"
+	    echo "$aconfdir/rwkeys"
+	    ;;
+	ra )
+	    echo "$aconfdir/rakeys"
+	    ;;
+    esac | while read keyfile; do
+	if ! grep '^'"$keyid"'$' "$keyfile" > /dev/null; then
+	    echo "$keyid" >> "$keyfile"
+	fi
+    done
+
+    rebuild_permissions "$name"
+
+    echo >&2 "key '$keyid' added to project '$name'."
+}
+
+# $1: name
+# $2: branch pattern
+addprojectpattern () {
+    name="$1"; shift
+    pattern="$1"; shift
+
+    if [ ! -e "$USHER_PROJECTDIR/$name" ]; then
+	echo >&2 "There is no project named '$name'."
+	exit 1
+    fi
+
+    confdir="$USHER_PROJECTDIR/$name"
+    aconfdir="$confdir/admin"
+
+    found_pattern=false
+    while read p; do
+	if [ "$p" = "$pattern" ]; then
+	    found_pattern=true
+	fi
+    done < "$aconfdir/patterns"
+    if ! $found_pattern; then
+	echo "$pattern" >> "$aconfdir/patterns"
+    fi
+
+    rebuild_permissions "$name"
+
+    echo >&2 "pattern '$pattern' added to project '$name'."
+}
+
 list () {
     grep '^ *server  *"' "$USHER_CONF" | cut -f2 -d'"' | while read name; do
 	text="$name"
@@ -478,10 +652,42 @@ case $1 in
 	    echo >&2 "Usher is already initialised."
 	    exit 1
 	fi
+
+	adminuser=admin
+	adminpass=admin
+	listenaddr=0.0.0.0:4691
+	adminaddr=127.0.0.1:12345
+	TEMP=`POSIXLY_CORRECT=yes getopt -o a:l:u:p: -n "usherctl init" -- "$@"`
+	eval set -- "$TEMP"
+	while true; do
+	    case "$1" in
+		-a )
+		    adminaddr="$2"; shift 2
+		    ;;
+		-l )
+		    listenaddr="$2"; shift 2
+		    ;;
+		-u )
+		    adminuser="$2"; shift 2
+		    ;;
+		-p )
+		    adminpass="$2"; shift 2
+		    ;;
+		--)
+		    shift
+		    break
+		    ;;
+	    esac
+	done
+
 	mkdir "$USHER_CONFDIR" "$USHER_CONFD" "$USHER_LOGDIR"
 	mkdir -p "$USHER_PROJECTDIR"
 	sed -e '1,/^# -----BEGIN globalconf-----$/d' \
 	    -e '/^# -----END globalconf-----$/,$d' \
+	    -e "s|%adminuser%|$adminuser|g" \
+	    -e "s|%adminpass%|$adminpass|g" \
+	    -e "s|%listenaddr%|$listenaddr|g" \
+	    -e "s|%adminaddr%|$adminaddr|g" \
 	    -e "s|%MTN%|$MTN|g" \
 	    -e "s|%USHER_LOGDIR%|$USHER_LOGDIR|g" \
 	    -e 's/^# //' \
@@ -570,6 +776,46 @@ case $1 in
 	rmproject "$1"
 	;;
 
+    addkey )
+	shift
+	name="$1"
+	shift
+
+	type=ro
+	key=
+	TEMP=`POSIXLY_CORRECT=yes getopt -o t: -n "usherctl addkey" -- "$@"`
+	eval set -- "$TEMP"
+	while true; do
+	    case "$1" in
+		-t )
+		    type="$2"; shift 2
+		    if [ "$type" != "ro" -a "$type" != "rw" -a "$type" != "ra" ]; then
+			echo >&2 "The type must be 'rw', 'ro' or 'ra'."
+		    fi
+		    ;;
+		--)
+		    shift
+		    break
+		    ;;
+	    esac
+	done
+
+	if [ -z "$name" ]; then
+	    echo >&2 "You have to give your project a name."
+	    exit 1
+	fi
+	
+	addprojectkey "$name" "$type"	# The key itself is on stdin
+	;;
+
+    addpattern )
+	shift
+	name="$1"
+	pattern="$2"
+
+	addprojectpattern "$name" "$pattern"
+	;;
+
     start | stop | restart | reload | status | list )
 	$1
 	;;
@@ -584,18 +830,113 @@ exit
 #### The following is sample text used to create scripts
 
 # -----BEGIN globalconf-----
-#   userpass "admin" "admin"
+#   userpass "%adminuser%" "%adminpass%"
 #   monotone "%MTN%"
-# listenaddr "0.0.0.0:4691"
-#  adminaddr "127.0.0.1:12345"
+# listenaddr "%listenaddr%"
+#  adminaddr "%adminaddr%"
 #     logdir "%USHER_LOGDIR%"
 # -----END globalconf-----
 
-# -----BEGIN monotonerc-----
-# ----------------------------------------------------------------------
-# ---- usherctl: this is a copy of contrib/get_passphrase_from_file.lua
-# ---- from the monotone distribution.
-# ----------------------------------------------------------------------
+# -----BEGIN init:both/monotonerc.in-----
+# ---- Load local hooks if they exist.
+# -- The way this is supposed to work is that hooks.d can contain symbolic
+# -- links to lua scripts.  These links MUST have the extension .lua
+# -- If the script needs some configuration, a corresponding lua file with
+# -- the extension .conf is the right spot.
+# ----
+# -- First load the configuration of the hooks, if applicable
+# includedirpattern(get_confdir() .. "/hooks.d/","*.conf")
+# -- Then load the hooks themselves
+# includedirpattern(get_confdir() .. "/hooks.d/","*.lua")
+# -----END init:both/monotonerc.in-----
+
+# Copied from monotone: contrib/authorize_remote_automate.lua
+# -----BEGIN init:both/hooks.d/authorize_remote_automate.lua-----
+# -- Copyright (c) 2010, Thomas Keller <address@hidden>
+# --                     Richard Levitte <address@hidden>
+# --
+# -- This script reads key identities from a file "remote-automate-permissions"
+# -- in the configuration directory and permits those authenticating with one
+# -- of those keys to perform dangerous (read/write) remote automate operations.
+# -- The format of the file is very simple, one key identity on every line.
+# -- Lines starting with # are ignore, as well as empty lines.
+# --
+# -- It's possible to configure this script to allow the performance of some
+# -- remote automate commands anonymously, through the variable
+# -- ARA_safe_commands, which has to be a table of commands as strings.
+# -- One example configuration, taken from the setup at code.monotone.ca, could
+# -- be this:
+# --
+# -- ARA_safe_commands = {
+# --    "get_corresponding_path", "get_content_changed", "tags", "branches",
+# --    "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
+# --    "packets_for_certs", "packet_for_rdata", "get_manifest_of",
+# --    "get_revision", "select", "graph", "children", "parents", "roots",
+# --    "leaves", "ancestry_difference", "toposort", "erase_ancestors",
+# --    "descendents", "ancestors", "heads", "get_file_of", "get_file",
+# --    "interface_version", "get_attributes", "content_diff",
+# --    "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
+# -- }
+# 
+# do
+#    local _safe_commands = {}
+#    if ARA_safe_commands then
+#       _safe_commands = ARA_safe_commands
+#    end
+# 
+#    local _save_get_remote_automate_permitted = get_remote_automate_permitted
+#    function get_remote_automate_permitted(key_identity, command, options)
+#       local permfile =
+# 	 io.open(get_confdir() .. "/remote-automate-permissions", "r")
+#       if (permfile == nil) then
+# 	 return false
+#       end
+# 
+#       -- See if the incoming key matches any of the key identities or
+#       -- patterns found in the permissions file.
+#       local matches = false
+#       local line = permfile:read()
+#       while (not matches and line ~= nil) do
+# 	 if not globish_match("#*", line) then
+# 	    local _, _, ln = string.find(line, "%s*([^%s]*)%s*")
+# 	    if ln == "*" then matches = true end
+# 	    if ln == key_identity.id then matches = true end
+# 	    if globish_match(ln, key_identity.name) then matches = true end
+# 	    line = permfile:read()
+# 	 end
+#       end
+#       io.close(permfile)
+#       if matches then return true end
+# 
+#       -- No matching key found, let's see if the command matches one the
+#       -- admin allowed to be performed anonymously
+#       for _,v in ipairs(_safe_commands) do
+# 	 if (v == command[1]) then
+# 	    return true
+# 	 end
+#       end
+# 
+#       -- No matches found anywhere, then don't permit this operation
+#       return false
+#    end
+# end
+# -----END init:both/hooks.d/authorize_remote_automate.lua-----
+
+# -----BEGIN init:public/hooks.d/authorize_remote_automate.conf-----
+# ARA_safe_commands = {
+#    "get_corresponding_path", "get_content_changed", "tags", "branches",
+#    "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
+#    "packets_for_certs", "packet_for_rdata", "get_manifest_of",
+#    "get_revision", "select", "graph", "children", "parents", "roots",
+#    "leaves", "ancestry_difference", "toposort", "erase_ancestors",
+#    "descendents", "ancestors", "heads", "get_file_of", "get_file",
+#    "interface_version", "get_attributes", "content_diff",
+#    "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
+# }
+# -----END init:public/hooks.d/authorize_remote_automate.conf-----
+
+# Copied from monotone: contrib/get_passphrase_from_file.lua
+# -----BEGIN init:both/hooks.d/get_passphrase_from_file.lua-----
 # -- This hook reads the 'passphrases' file from the confdir.  It expects the
 # -- file to be formatted as follows:
 # --
@@ -611,120 +952,10 @@ exit
 #    local line = permfile:read()
 #    while (line ~= nil) do
 #       local _, _, key, passphrase = string.find(line, "%s*([^%s]*)%s*\"(.*)\"%s*")
-#       if keypair_id.given_name == key then
-#          return passphrase
-#       end
+#       if keypair_id.given_name == key then return passphrase end
 #       line = permfile:read()
 #    end
 #    io.close(permfile)
 #    return false
 # end
-# ----------------------------------------------------------------------
-# 
-# function get_remote_automate_permitted(key_identity, command, options)
-#     -- Use the key identity from clients that may use dangerous remote commands
-#     if (key_identity.id == "?????") then
-#         return true
-#     end
-# 
-#     local read_only_commands = {
-#         "get_corresponding_path", "get_content_changed", "tags", "branches",
-#         "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
-#         "packets_for_certs", "packet_for_rdata", "get_manifest_of",
-#         "get_revision", "select", "graph", "children", "parents", "roots",
-#         "leaves", "ancestry_difference", "toposort", "erase_ancestors",
-#         "descendents", "ancestors", "heads", "get_file_of", "get_file",
-#         "interface_version", "get_attributes", "content_diff",
-#         "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
-#     }
-# 
-#     for _,v in ipairs(read_only_commands) do
-#         if (v == command[1]) then
-#             return true
-#         end
-#     end
-# 
-#     return false
-# end
-# 
-# ---- Load local hooks if they exist.
-# -- The way this is supposed to work is that hooks.d can contain symbolic
-# -- links to lua scripts.  These links MUST have the extension .lua
-# -- If the script needs some configuration, a corresponding lua file with
-# -- the extension .conf is the right spot.
-# ----
-# -- First load the configuration of the hooks, if applicable
-# includedirpattern(get_confdir() .. "/hooks.d/","*.conf")
-# -- Then load the hooks themselves
-# includedirpattern(get_confdir() .. "/hooks.d/","*.lua")
-# -----END monotonerc-----
-
-# -----BEGIN priv:addclientkeys-----
-# #! /bin/sh
-# 
-# mtn='%amtn%'
-# confdir='%confdir%'
-# listenport='%listenport%'
-# name='%name%'
-# user='%user%'
-# group='%group%'
-# 
-# set -e
-# cd "$confdir"
-# 
-# eval $mtn read 2> /dev/null
-# rm -f "$confdir/write-permissions"
-# touch "$confdir/write-permissions"
-# echo 'pattern "*"' > "$confdir/read-permissions"
-# chmod 0640 "$confdir/read-permissions"
-# chmod 0640 "$confdir/write-permissions"
-# eval $mtn ls keys | grep '^[0-9a-f]' | cut -f1 -d' ' | sort | uniq | \
-#     while read K; do
-#         echo $K >> "$confdir/write-permissions"
-#         echo "  allow \"$K\"" >> "$confdir/read-permissions"
-#         if /etc/init.c/usher status >/dev/null 2>/dev/null; then
-#             eval $mtn push mtn://127.0.0.1:$listenport/$name '"*"' \
-#                 --key-to-push $K 2> /dev/null
-#         else
-#             eval $mtn push file://$confdir/database.mtn '"*"' \
-#                 --key-to-push $K 2> /dev/null
-#         fi
-#     done
-# if [ -n "$user" -a -n "$group" ]; then
-#     chown ${user}:${group} "$confdir/write-permissions"
-#     chown ${user}:${group} "$confdir/read-permissions"
-# fi
-# -----END priv:addclientkeys-----
-
-# -----BEGIN pub:addclientkeys-----
-# #! /bin/sh
-# 
-# mtn='%amtn%'
-# confdir='%confdir%'
-# listenport='%listenport%'
-# name='%name%'
-# user='%user%'
-# group='%group%'
-#
-# set -e
-# cd "$confdir"
-# 
-# eval $mtn read 2> /dev/null
-# rm -f "$confdir/write-permissions"
-# touch "$confdir/write-permissions"
-# chmod 0640 "$confdir/write-permissions"
-# eval $mtn ls keys | grep '^[0-9a-f]' | cut -f1 -d' ' | sort | uniq | \
-#     while read K; do
-#         echo $K >> "$confdir/write-permissions"
-#         if /etc/init.c/usher status >/dev/null 2>/dev/null; then
-#             eval $mtn push mtn://127.0.0.1:$listenport/$name '"*"' \
-#                 --key-to-push $K 2> /dev/null
-#         else
-#             eval $mtn push file://$confdir/database.mtn '"*"' \
-#                 --key-to-push $K 2> /dev/null
-#         fi
-#     done
-# if [ -n "$user" -a -n "$group" ]; then
-#     chown ${user}:${group} "$confdir/write-permissions"
-# fi
-# -----END pub:addclientkeys-----
+# -----END init:both/hooks.d/get_passphrase_from_file.lua-----
============================================================
--- src/channel.cc	7e6b6bbae6a84041ec840bedf5816bd6e116e5ea
+++ src/channel.cc	28d584b7185308aeab9297b3c9ceae03718a9e65
@@ -24,7 +24,7 @@ channel::channel(sock & c, server_manage
 
 channel::channel(sock & c, server_manager &sm)
  : num(++counter),
-  cli(c), srv(-1),
+   cli(c),
   have_routed(false), no_server(false),
   manager(sm)
 {
@@ -45,7 +45,7 @@ channel::~channel()
 
 channel::~channel()
 {
-  if (srv && !no_server)
+  if (srv != -1 && !no_server)
     manager.disconnect_from_server(srv, name);
 }
 
============================================================
--- src/channel.hh	3a97687c17a68c983872de2792defd9e48028168
+++ src/channel.hh	21231cc383b16935ac33a349718e5aa775341c45
@@ -17,7 +17,7 @@ using boost::shared_ptr;
 #include <boost/shared_ptr.hpp>
 using boost::shared_ptr;
 
-struct server_manager;
+class server_manager;
 
 struct channel
 {
============================================================
--- src/server.hh	dd153b5671f0b9560be8b817849731419e5b8fe4
+++ src/server.hh	6a57214c24d5c35c705276dcae8415dfcabf6c6e
@@ -24,7 +24,7 @@ using boost::weak_ptr;
 #include <boost/weak_ptr.hpp>
 using boost::weak_ptr;
 
-struct server_manager;
+class server_manager;
 
 struct serverstate
 {
@@ -38,8 +38,9 @@ std::ostream & operator<<(std::ostream &
 };
 std::ostream & operator<<(std::ostream & os, serverstate const & ss);
 
-struct server
+class server
 {
+  friend class server_manager;
   bool enabled;
   bool local;
   int pid;
@@ -51,6 +52,7 @@ struct server
   int last_conn_time;
   server_manager &manager;
   weak_ptr<server> me;
+public:
   server(server_manager &sm);
   ~server();
   serverstate get_state();
============================================================
--- src/server_manager.cc	0abe47e13dd931c522aa1a7fb828502d63531a6e
+++ src/server_manager.cc	f4a5b6fe2d917f24ce56c133ee347b9b3e91e50b
@@ -20,8 +20,9 @@ using std::make_pair;
 #include <boost/lexical_cast.hpp>
 //#include <iostream>
 
-serversock::serversock(sock const &o)
- : sock(o)
+serversock::serversock() : sock(-1) { }
+serversock::serversock(sock const &o, string s)
+  : sock(o), srv(s)
 {
 }
 
@@ -309,11 +310,10 @@ server_manager::connect_to_server(string
   if (!srv)
     throw std::logic_error("usher internal error");
   sock s = srv->connect(name);
-  serversock ss(s);
   map<shared_ptr<server>, serverdata>::iterator i = servers.find(srv);
   if (i == servers.end())
     throw std::logic_error("server_manager is inconsistent");
-  ss.srv = i->second.name;
+  serversock ss(s, i->second.name);
   ++total_connections;
   if (srv->local && srv->connection_count == 1)
     {
@@ -325,7 +325,7 @@ server_manager::disconnect_from_server(s
 server_manager::disconnect_from_server(serversock const &s,
                                        string const &name)
 {
-  map<string, shared_ptr<server> >::iterator i = by_name.find(s.srv);
+  map<string, shared_ptr<server> >::iterator i = by_name.find(s.servername());
   if (i == by_name.end())
     return;
   i->second->disconnect(name);
============================================================
--- src/server_manager.hh	fc8ad29b28f82cae3b26955995afdad8f1276a5a
+++ src/server_manager.hh	1d1f3a16329bdf11b69fb7593d048d95c65edc8d
@@ -27,11 +27,13 @@ struct serverlist_reader;
 
 struct serverlist_reader;
 
-struct serversock : public sock
+class serversock : public sock
 {
   string srv;
-  serversock(sock const &o);
-  operator bool() {return !srv.empty();}
+public:
+  serversock();
+  serversock(sock const &o, string s);
+  string const & servername() const { return srv; }
 };
 
 class server_manager
============================================================
--- src/sock.hh	0917e736d673fa6d15fcefea8f1f0e16a63b9bc2
+++ src/sock.hh	b077f32cc61674e13b9c3bc138c924c41b23ceb1
@@ -15,10 +15,11 @@ struct buffer;
 
 struct buffer;
 
-struct sock
+class sock
 {
   int *s;
   static std::set<int*> all_socks;
+public:
   operator int();
   sock(int ss);
   sock(sock const & ss);
============================================================
--- README	b968eb93f8b8ce88d822e9ddc52b563f1742a147
+++ README	84610efd11606729230d94fb905e5e4695328c7b
@@ -13,4 +13,4 @@
 use your new subclass instead of basic_io_serverlist_reader.
 
 The tests use 'socat', and assume the monotone in your $PATH is at least
-version 0.45.
\ No newline at end of file
+version 0.45.
============================================================
--- NEWS	a9b8cb5b3dc0ec686519bbb81dc1058d30fb1099
+++ NEWS	41f6acc0681f23e164e7d8dc6be0738de13a8bf1
@@ -1,5 +1,13 @@
-Xxx Xxx 99 99:99:99 UTC 2010
+Xxx Xxx 99 99:99:99 UTC 2011
 
+        1.0 release.
+
+        General
+
+        - [put stuff here]
+
+Sat Nov 06 03:04:58 UTC 2010
+
         0.99 release.
 
         General
============================================================
--- /dev/null	
+++ release-checklist.txt	305136c17d554f0b16fdab39873c5814cc64691a
@@ -0,0 +1,16 @@
+* test 'make check' or 'make distcheck' on a couple different systems
+
+* look at what's changed since the last release, and make sure there are documentation
+  updates where appropriate
+
+* make sure NEWS is filled out and presentable
+
+* make sure the date at the top of NEWS is filled out
+
+* take the "~dev" out of the version in configure.in
+
+* commit; run autoreconf -i, configure, and "make distcheck" in a clean checkout
+
+* add a tag, post the tarball, and email monotone-devel
+
+* add a new blank release date at the top of NEWS, increment the version number and add "~dev"

reply via email to

[Prev in Thread] Current Thread [Next in Thread]