#!/bin/bash -e export TMPDIR="`mktemp -d --tmpdir pbs-absrepo-convert.XXXXXXXXXX`" cleanup() { msg "$(gettext "Removing temporary files...")" echo rm -rf "$TMPDIR" } trap cleanup EXIT . /usr/bin/libremessages abort() { echo # force a fresh line error "$(gettext "Aborting...")" cleanup } ## # Usage: collect-data MODE # MODE is either 'correct' or 'fast' # # Assumptions: # - currently in a working copy of the repo # - git branch "master" exists and is untouched # - TMPDIR is set and exists # Effects: # - creates file "${TMPDIR}/commits" # - creates file "${TMPDIR}/find" # - creates file "${TMPDIR}/packages" # - creates file "${TMPDIR}/architectures" ## collect-data() { msg "$(gettext "Collecting package data...")" [[ $# = 1 ]] || { usage; return 1; } local mode=$1 case "$mode" in correct) git log --pretty=format:'%H' master > "${TMPDIR}/commits";; fast) echo master > "${TMPDIR}/commits";; *) usage; return 1;; esac # actual data collection ############################################### local count="$(wc -l < "${TMPDIR}/commits")" cat -n "${TMPDIR}/commits" | while read n commit; do printf '\rscanning commit %s (%d/%d)' "$commit" "$n" "$count" >> /dev/tty git ls-tree -rd --name-only "$commit" done | fgrep /repos/ | sort -u > "${TMPDIR}/find" echo # newline # extract some things ################################################## # packages { < "${TMPDIR}/find" sed -e 's|^\.||' -e 's|/.*||' } | sort -u > "${TMPDIR}/packages" # architectures { echo master < "${TMPDIR}/find" sed -e 's/.*-//' -e '/^any$/d' } | sort -u > "${TMPDIR}/architectures" } ## # Usage: convert-package SOURCE PACKAGE # Assumptions: # - currently in a working copy of the repo # - TMPDIR is set # Effects: # - creates git branch "packages/${SOURCE}/${PACKAGE}" # - creates file "${TMPDIR}/packages-${PACKAGE}.commits" # Side effects: # - changes git working tree # - prints output of git commands ## convert-package() { [[ $# = 2 ]] || { usage; return 1; } local source=$1 local package=$2 local branch="packages/${source}/${package}" local dir if git checkout "packages/${package}" &>/dev/null; then # special case (common; optimization) git checkout -b "$branch" git branch -D "packages/${package}" dir=trunk else # general case (uncommon) git checkout -b "$branch" orig dir="${package}/trunk" fi git filter-branch -f --prune-empty --subdirectory-filter "$dir" "$branch" git log --pretty=format:'%T %H' > "${TMPDIR}/packages-${package}.commits" } ## # Usage: convert-packages SOURCE # Assumptions: # - meets assumptions of `convert-package` # - TMPDIR is set # - file "${TMPDIR}/packages" contains a newline-separated list of packages # Effects: # - runs `convert-package` for every package listed in "${TMPDIR}/packages" # - prints status updates about what it is doing ## convert-packages() { msg "$(gettext "Converting packages...")" [[ $# = 1 ]] || { usage; return 1; } local source=$1 local count="$(wc -l < "${TMPDIR}/packages")" cat -n "${TMPDIR}/packages" | while read n package; do msg2 "$(gettext "(%d/%d) %s")" "$n" "$count" "$package" convert-package "$source" "$package" done } ## # Usage: convert-arch ARCH # Assumptions: # - currently in a working copy of the repo # Effects: # - creates git branch "${ARCH}" # - TMPDIR is set # - creates file "${TMPDIR}/missing-packages.${ARCH}" # Side effects: # - changes git working tree # - prints output of git commands ## convert-arch() { [[ $# = 1 ]] || { usage; return 1; } local arch=$1 touch "${PKGDIR}/missing-packages.${arch}.tmp" git checkout orig git checkout -b "$arch" git filter-branch -f --tree-filter \ "pbs-absrepo-convert--filterarch $arch" "$arch" sort -u \ < "${PKGDIR}/missing-packages.${arch}.tmp" \ > "${PKGDIR}/missing-packages.${arch}" rm -f "${PKGDIR}/missing-packages.${arch}.tmp" } ## # Usage: convert-arches # Assumptions: # - meets assumptions of `convert-arch` # - file "${TMPDIR}/architectures" contains a newline-separated list of arches # - file "${TMPDIR}/packages-${PACKAGE}.commits" exists for every package # 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...")" [[ $# = 0 ]] || { usage; return 1; } local count="$(wc -l < "${TMPDIR}/architectures")" cat -n "${TMPDIR}/architectures" | while read n arch; do msg2 "$(gettext "(%d/%d) %s")" "$n" "$count" "$arch" convert-arch "$arch" done } main() { trap abort EXIT [[ $# = 1 ]] || { usage; return 1; } local source=$1 local cachedir="$(pbs-plumb-config get core.cachedir)" local sourcedir="$(pbs-plumb-config get core.sourcedir)" # init ################################################################# msg "$(gettext "Creating working copy...")" git clone "${cachedir}/${source}.git" "${TMPDIR}/repo" cd "${TMPDIR}/repo" git checkout -b orig collect-data fast git branch -D master # main ################################################################# convert-packages "$source" convert-arches "$source" # save results ######################################################### msg "$(gettext "Copying into source directory...")" [[ -d "$sourcedir" ]] || mkdir -p "$sourcedir" 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 trap cleanup EXIT } main "$@"