carbon-core-system

Integration repository for versioned configuration and software on Carbon
git clone https://ccx.te2000.cz/git/carbon-core-system
Log | Files | Refs | Submodules

update-bzr (4064B)


      1 #!/bin/zsh
      2 setopt no_unset warn_create_global extended_glob
      3 zmodload -F zsh/stat b:zstat || exit $?
      4 zmodload -m -F zsh/files b:zf_\* || exit $?
      5 zmodload zsh/zutil || exit $?
      6 
      7 die_ret() {
      8 	local ret
      9 	ret=$1
     10 	shift
     11 	echo >&2 "$@"
     12 	exit $ret
     13 }
     14 die() {
     15 	die_ret 1 "$@"
     16 }
     17 cd $0:h || exit $?
     18 
     19 pretend() {
     20 	: "$@"
     21 }
     22 typeset -ft pretend
     23 
     24 brz=${commands[brz]:-bzr}
     25 
     26 load_sources() {
     27 	unset repo_sources
     28 	typeset -gA repo_sources
     29 	unset repos
     30 	typeset -ga repos
     31 
     32 	local name url
     33 	<./bzr/sources while IFS=$'\t' read name url; do
     34 		[[ -n "$name" && -n "$url" ]] || die "Malformed sources file"
     35 		(( $+repo_sources[$name] )) && die "Duplicate repo name: ${(qqq)name}"
     36 		repo_sources[$name]=$url
     37 		repos+=( $name )
     38 	done
     39 }
     40 
     41 make_revisions_new() {
     42 	unset revisions_new
     43 	typeset -gA revisions_new
     44 
     45 	local name url
     46 	local -a info
     47 	for name in $repos; do
     48 		info=( $($brz version-info $repo_sources[$name]) ) ||
     49 			die_ret $? brz version-info failed
     50 		[[ $info[1] == "revision-id:" ]] ||
     51 			die malformed brz version-info output
     52 		revisions_new[$name]=$info[2]
     53 		printf '%s\t%s\n' $name $info[2] || exit $?
     54 	done
     55 }
     56 
     57 load_old_revisions() {
     58 	unset revisions_old
     59 	typeset -gA revisions_old
     60 
     61 	local name revid
     62 	<./bzr/revisions while IFS=$'\t' read name revid; do
     63 		[[ -n "$name" && -n "$revid" ]] || die "Malformed revisions file"
     64 		(( $+revisions_old[$name] )) && die "Duplicate repo name: ${(qqq)name}"
     65 		revisions_old[$name]=$revid
     66 	done
     67 }
     68 
     69 compare_revisions() {
     70 	unset repo_status
     71 	typeset -gA repo_status
     72 	typeset -ga repos_modified repos_added repos_deleted repos_same
     73 
     74 	local name old_revid
     75 	for name in $repos; do
     76 		if ! (($+revisions_old[$name])); then
     77 			repo_status[$name]=A
     78 			repos_added+=( $name )
     79 		elif [[ $revisions_new[$name] != $revisions_old[$name] ]]; then;
     80 			repo_status[$name]=M
     81 			repos_modified+=( $name )
     82 		else
     83 			repos_same+=( $name )
     84 		fi
     85 	done
     86 	for name in "${(@k)revisions_old}"; do
     87 		if ! (($+revisions_new[$name])); then
     88 			repo_status[$name]=D
     89 			repos_deleted+=( $name )
     90 		fi
     91 	done
     92 }
     93 
     94 bzrlog() {
     95 	# first argument needs to be revision range
     96 	$brz log --show-diff --long --forward -r "$@"
     97 }
     98 
     99 show_diffs() {
    100 	local name next_revid
    101 	for name in $repos_modified; do 
    102 		printf "== showing differences for %s == %s -> %s ==\n" $name $revisions_old[$name] $revisions_new[$name]
    103 
    104 		# Displayed revision range is inclusive, but we already have the first revision.
    105 		next_revid=$(
    106 			bzr log --long --forward --show-ids \
    107 			-r "revid:$revisions_old[$name]..revid:$revisions_new[$name]"  \
    108 			$repo_sources[$name] \
    109 			| awk '/^revision-id: /{if(x){print $2;exit};x=1}'
    110 		)
    111 		bzrlog "revid:$next_revid..revid:$revisions_new[$name]" $repo_sources[$name]
    112 	done
    113 	for name in $repos_added; do 
    114 		printf "== showing differences for %s == %s -> %s ==\n" $name start $revisions_new[$name]
    115 		bzrlog "..revid:$revisions_new[$name]" $repo_sources[$name]
    116 	done
    117 	echo ---
    118 	printf '%d repositories modified' $#repos_modified
    119 	(( $#repos_modified )) && printf ': %s' "$repos_modified"
    120 	print
    121 
    122 	printf '%d repositories added' $#repos_added
    123 	(( $#repos_added )) && printf ': %s' "$repos_added"
    124 	print
    125 
    126 	printf '%d repositories deleted' $#repos_deleted
    127 	(( $#repos_deleted )) && printf ': %s' "$repos_deleted"
    128 	print
    129 
    130 	printf '%d repositories same' $#repos_same
    131 	(( $#repos_same )) && printf ': %s' "$repos_same"
    132 	print
    133 }
    134 
    135 prompt_commit() {
    136 	local REPLY
    137 	local -a msg
    138 	diff -u ./bzr/revisions ./bzr/revisions.new
    139 	echo -n "Apply and commit changes? "
    140 	read -q || exit 0
    141 	echo 
    142 	msg=(
    143 		"Update bzr repositories."
    144 		"Added: "$^repos_added
    145 		"Changed: "$^repos_modified
    146 		"Deleted: "$^repos_deleted
    147 	)
    148 	mv -v ./bzr/revisions.new ./bzr/revisions || exit $?
    149 	git add ./bzr/revisions || exit $?
    150 	git commit -m "${(F)msg}" ./bzr/revisions || exit $?
    151 }
    152 
    153 main() {
    154 	load_sources
    155 	make_revisions_new >bzr/revisions.new
    156 
    157 	load_old_revisions
    158 	compare_revisions
    159 	#printf "%s\t%s\n" "${(@vk)repo_status}"
    160 	show_diffs | less --quit-if-one-screen
    161 	if ! (( $#repos_added + $#repos_modified + $#repos_deleted )); then
    162 		echo "Nothing to do"
    163 		exit 0
    164 	fi
    165 	prompt_commit
    166 }
    167 #typeset -ft main
    168 main