#!/bin/sh -efu . shell-error . shell-getopt show_help() { cat <<-EOF Usage: $PROG [options] Utility to convert submodules to brunches. Options: -p, --prefix=STR add STR to branch's names; -f, --force don't check untracked and modified files; -v, --verbose print a message for each action; -V, --version print program version and exit; -h, --help show this text and exit. Report bugs to http://bugzilla.altlinux.org/ EOF exit } print_version() { cat <<-EOF $PROG version $PROG_VERSION Written by Alexey Gladkov Copyright (C) 2010 Alexey Gladkov This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. EOF exit } submodule_remotes= workdir= exit_handler() { local rc=$? if [ "$rc" != 0 ]; then for s in $submodule_remotes; do git remote rm "$s" done git reset --hard HEAD fi [ ! -d "$workdir" ] || rm -rf -- "$workdir" } TEMP=`getopt -n $PROG -o "f,h,p:,v,V" -l "force,help,prefix:,verbose,version" -- "$@"` || show_usage eval set -- "$TEMP" force= prefix= while :; do case "$1" in -p|--prefix) shift prefix="$1" ;; -f|--force) force=1 ;; -h|--help) show_help ;; -V|--version) print_version ;; -v|--verbose) verbose=-v ;; --) shift; break ;; *) fatal "unrecognized option: $1" ;; esac shift done if [ -z "$force" ]; then out="$(git diff-index --cached --name-only HEAD)" [ -z "$out" ] || fatal "Changed files found in the index." out="$(git diff --name-only && git ls-files --directory --others --exclude-per-directory=.gitignore)" [ -z "$out" ] || fatal "Untracked or modified files found." fi trap exit_handler EXIT QUIT HUP INT TERM workdir="$(mktemp -dt "$PROG.XXXXXXXXX")" git submodule init git submodule status | while read commitish path dummy; do printf '%s\n' "$path" done > "$workdir/submodules" verbose "Checking submodules ..." if [ ! -s "$workdir/submodules" ]; then message "no submodules found for this repository." exit 0 fi verbose "Checking remote branches ..." git remote > "$workdir/remotes" while read name; do while read remote; do [ "$name" != "$remote" ] || fatal "$remote: remote already exists." done < "$workdir/remotes" done < "$workdir/submodules" while read name; do branch="$prefix$name" message "Converting '$name' submodule to '$branch' branch ..." url="$(git config --get "submodule.$name.url")" || fatal "$name: url not found" submodule_remotes="$submodule_remotes $branch" git remote add -f "$branch" "$url" find "$name" -mindepth 1 -maxdepth 1 -execdir rm $verbose -rf -- '{}' \+ git merge -q -s ours --no-commit "$branch/master" git read-tree --prefix="$name" -u "$branch/master" git commit -m "Merge '$name' as our subdirectory" done < "$workdir/submodules" while read name; do verbose "Removing '$name' submodule section from git config ..." git config --remove-section "submodule.$name" done < "$workdir/submodules"