#!/bin/bash -euE . libremessages cmd="${0##*/}" cleanup() { msg "$(gettext "Removing temporary files...")" echo rm -rf "$TMPDIR" } abort() { echo # force a fresh line error "$(gettext "Aborting...")" cleanup } ## # Usage: trailing-newline FILE # # Adds a trailing newline to ${FILE} if there isn't one. # # Useful because different versions of git are inconsistent about # when there is one on output. ### trailing-newline() { local file=$1 if [[ "`sed -n '$p' "$file"|wc -l`" = 0 ]]; then echo >> "$file" fi } ## # Usage: collect-data # # Assumptions: # - currently in the working repo # Effected by: # - file ../missing-packages # Effects: # - creates file "../find" # - creates file "../packages" # - creates file "../architectures" # Side effects: # - creates file "${TMPDIR}/commits" ## collect-data() { local mode=fast # 'correct' or 'fast # 'fast' may omit some packages that have been deleted. msg "$(gettext "Collecting package data...")" case "$mode" in correct) git log --pretty=format:'%H' master > "${TMPDIR}/commits";; fast) git log -n1 --pretty=format:'%H' master > "${TMPDIR}/commits";; *) usage; return 1;; esac trailing-newline "${TMPDIR}/commits" # actual data collection ############################################### local count="$(wc -l < "${TMPDIR}/commits")" cat -n "${TMPDIR}/commits" | while read n commit; do printf "\\r$(gettext "Scanning commit %s (%d/%d)")" "$commit" "$n" "$count" >> /dev/tty git ls-tree -rd --name-only "$commit" done | fgrep /repos/ | sort -u > ../find echo # newline # extract some things ################################################## # packages { if [[ $mode = fast ]]; then cat ../{packages,missing-packages} 2>/dev/null || true fi < ../find sed -e 's|^\.||' -e 's|/.*||' } | sort -u > ../packages.tmp mv ../packages{.tmp,} # architectures { echo master < ../find sed -e 's/.*-//' -e '/^any$/d' } | sort -u > ../architectures } ## # Usage: convert-package PACKAGE # # Assumptions: # - currently in the working repo # Effects: # - creates git branch "pkgs/${PACKAGE}" # - creates file "../pkg-${PACKAGE}.commits" # Side effects: # - changes git working tree # - prints output of git commands ## convert-package() { local package=$1 local obranch="pkgs/${package}" local ibranch local dir if git checkout "packages/${package}" &>/dev/null; then # special case (common; optimization) ibranch="packages/${package}" dir=trunk else # general case (uncommon) ibranch=master dir="${package}/trunk" fi git rewrite-branch --svn "$ibranch" "$obranch" \ --prune-empty --subdirectory-filter "$dir" if [[ $ibranch != master ]]; then git branch -D "$ibranch" fi git log "$obranch" --pretty=format:'%T %H' \ > "../pkg-${package}.commits" } ## # Usage: convert-packages # Assumptions: # - currently in the working repo # - file "../packages" contains a newline-separated list of packages # Effects: # - runs `convert-package` for every package listed in "../packages" # - prints status updates about what it is doing ## convert-packages() { msg "$(gettext "Converting packages...")" local count="$(wc -l < ../packages)" cat -n ../packages | while read n package; do msg2 "$(gettext "(%d/%d) %s")" "$n" "$count" "$package" convert-package "$package" done } ## # Usage: convert-arch ARCH # Assumptions: # - currently in the working repo # - file "../packages-${PACKAGE}.commits" exists for every package # Effects: # - creates git branch "${ARCH}" # - creates file "${TMPDIR}/missing-packages/${ARCH}" # Side effects: # - changes git working tree # - prints output of git commands ## convert-arch() { local arch=$1 mkdir -p "${TMPDIR}/missing-packages" touch "${TMPDIR}/missing-packages/${arch}.tmp" git rewrite-branch master "$arch" \ --tree-filter "${cmd}--filterarch $arch" sort -u \ < "${TMPDIR}/missing-packages/${arch}.tmp" \ > "${TMPDIR}/missing-packages/${arch}" rm -f "${TMPDIR}/missing-packages/${arch}.tmp" } ## # Usage: convert-arches # Assumptions: # - currently in the working repo # - file "../architectures" contains a newline-separated list of arches # Effects: # - runs `convert-arch` for every arch listed in "${TMPDIR}/architectures" # - prints status updates about what it is doing ## convert-arches() { msg "$(gettext "Converting architectures...")" local count="$(wc -l < "../architectures")" cat -n "../architectures" | while read n arch; do msg2 "$(gettext "(%d/%d) %s")" "$n" "$count" "$arch" convert-arch "$arch" done } usage() { echo "Usage: ${0##*/} SOURCE" echo "Convert SOURCE from the absgit format to the pbs format." echo echo "SOURCE must be configured in /etc/libretools.d/pbs-convert.conf" } main() { in_array '-h' "$@" && { usage; return 0; } [[ $# = 1 ]] || { usage >&2; return 1; } export TMPDIR="`mktemp -d --tmpdir ${cmd}.XXXXXXXXXX`" trap abort EXIT local source=$1 local cache="$(pbs-plumb-config get core.cachedir)/${source}.git" local workdir="$(pbs-plumb-config get core.rewritedir)/${source}" local sourcedir="$(pbs-plumb-config get core.sourcedir)" # init ###################################d############################## if [[ ! -d "${workdir}" ]]; then msg "$(gettext "Creating working copy...")" git clone "$cache" "${workdir}/repo" fi cd "${workdir}/repo" # main ################################################################# collect-data fast convert-packages convert-arches # save results ######################################################### msg "$(gettext "Copying into source directory...")" [[ -d "$sourcedir" ]] || mkdir -p "$sourcedir" # copy git repo git clone --mirror "${TMPDIR}/repo" "${sourcedir}/${source}.new.git" if [[ -d "${sourcedir}/${source}.git" ]]; then mv "${sourcedir}/${source}"{,.old}.git fi mv "${sourcedir}/${source}"{.new,}.git if [[ ! -d "${sourcedir}/${source}.old.git" ]]; then rm -rf "${sourcedir}/${source}".old.git fi # copy other data cp -f "../packages" "${sourceir}/${source}.packages" cat "${TMPDIR}"/missing-packages/* > "${sourceir}/${source}.missing-packages" trap cleanup EXIT } main "$@"