#!/bin/bash # # git-darcs - bidirectional operation between a darcs repo and git # # Copyright (c) 2008, 2010 by Miklos Vajna # # Based on git-bzr, which is # # Copyright (c) 2008 Pieter de Bie # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. # add() { name="$1" shift location="$1" shift if ! [ -n "$name" -a -n "$location" ]; then echo "Usage: git darcs add name location [darcs-fast-export options]" return 1 fi if git remote show |grep -q $name; then echo "There is already a remote with that name" return 1 fi if [ -n "$(git config git-darcs.$name.location)" ]; then echo "There is already a darcs repo with that name" return 1 fi repo=$location/_darcs if [ ! -d $repo ] && ! wget --quiet --spider $repo; then echo "Remote is not a darcs repository" return 1 fi git config git-darcs.$name.location $location echo "Darcs repo $name added. You can fetch it with 'git darcs fetch $name'" if ! [ -z "$*" ]; then git config git-darcs.$name.darcs-fast-export-options "$*" echo "darcs-fast-export will get options: $*" fi } get_location() { l=$(git config git-darcs.$remote.location) if [ -z "$l" ]; then echo "Cannot find darcs remote with name '$remote'." >&2 return 1 fi echo $l } fetch() { remote="$1" shift if ! [ -n "$remote" -a -z "$*" ]; then echo "Usage: git darcs fetch reponame" return 1 fi location=$(get_location $remote) || return $? git_map=$git_dir/darcs-git/$remote-git-map darcs_map=$git_dir/darcs-git/$remote-darcs-map common_opts="--working $git_dir/darcs-git/repo --logfile $git_dir/darcs-git/fetch.log --git-branch=refs/remotes/darcs/$remote" dfe_opts=$(git config git-darcs.$remote.darcs-fast-export-options) pre_fetch="$(git config git-darcs.$remote.pre-fetch)" if [ -n "$pre_fetch" ]; then $pre_fetch fi if [ ! -f $git_map -a ! -f $darcs_map ]; then echo "There doesn't seem to be an existing refmap." echo "Doing an initial import" mkdir -p $git_dir/darcs-git darcs-fast-export --export-marks=$darcs_map $common_opts $dfe_opts $location | \ git fast-import --export-marks=$git_map elif [ -f $git_map -a -f $darcs_map ]; then echo "Updating remote $remote" old_rev=$(git rev-parse refs/remotes/darcs/$remote) darcs-fast-export --import-marks=$darcs_map --export-marks=$darcs_map $common_opts $dfe_opts $location | \ git fast-import --quiet --import-marks=$git_map --export-marks=$git_map new_rev=$(git rev-parse refs/remotes/darcs/$remote) if [ "$old_rev" != "$new_rev" ]; then echo "Fetched the following updates:" git shortlog $old_rev..$new_rev else echo "Nothing fetched." return 0 fi else echo "One of the mapfiles is missing! Something went wrong!" return 1 fi post_fetch="$(git config git-darcs.$remote.post-fetch)" if [ -n "$post_fetch" ]; then $post_fetch fi } pull() { remote="$1" shift if ! [ -n "$remote" -a -z "$*" ]; then echo "Usage: git darcs pull reponame" return 1 fi fetch $remote || return $? # see if we need to merge or rebase branch=$(git symbolic-ref HEAD|sed 's|.*/||') if [ "$(git config branch.$branch.rebase)" = "true" ]; then git rebase refs/remotes/darcs/$remote else git merge refs/remotes/darcs/$remote fi } push() { remote="$1" shift if ! [ -n "$remote" -a -z "$*" ]; then echo "Usage: git darcs push reponame" return 1 fi location=$(get_location $remote) || return $? if [ -n "$(git rev-list --left-right HEAD...refs/remotes/darcs/$remote | sed -n '/^>/ p')" ]; then echo "HEAD is not a strict child of $remote, cannot push. Merge first" return 1 fi if [ -z "$(git rev-list --left-right HEAD...refs/remotes/darcs/$remote | sed -n '/^" return 1 fi for remote in $(git for-each-ref --format='%(refname)' refs/remotes/darcs) do remote=`basename $remote` git_map=$git_dir/darcs-git/$remote-git-map darcs_map=$git_dir/darcs-git/$remote-darcs-map if [ ! -f $git_map -o ! -f $darcs_map ] then echo "Missing mappings for remote $remote" return 1 fi for row in `sed -n -e "/:.* $sha1.*/ s/[^ ]*/&/p" $git_map` do sed -n -e "/$row / {s/[^ ]*//; s/.*/$remote\t&/p}" $darcs_map done done } # Find the git commit(s) supporting a darcs patch prefix find_git() { patch="$1" shift if [ -z "$patch" -o -n "$*" ] then echo "Usage: git darcs find-git " return 1 fi for remote in $(git for-each-ref --format='%(refname)' refs/remotes/darcs) do remote=`basename $remote` git_map=$git_dir/darcs-git/$remote-git-map darcs_map=$git_dir/darcs-git/$remote-darcs-map if [ ! -f $git_map -o ! -f $darcs_map ] then echo "Missing mappings for remote $remote" return 1 fi for row in `sed -n -e "/:.* $patch.*/ s/[^ ]*/&/p" $darcs_map` do sed -n -e "/$row / {s/[^ ]* \(.*\)/$remote\t\1/p}" $git_map done done } git rev-parse 2> /dev/null if [ $? != 0 ]; then echo "Must be inside a git repository to work" exit 1 fi git_dir=$(git rev-parse --git-dir) # make it absolute cd $git_dir git_dir=$(pwd) cd - >/dev/null command="$1" shift case $command in add|push|fetch|pull|list) ;; find-darcs) command=find_darcs ;; find-git) command=find_git ;; *) echo "Usage: git darcs [COMMAND] [OPTIONS]" echo "Commands: add, push, fetch, pull, list, find-darcs, find-git" exit 1 ;; esac up=$(git rev-parse --show-cdup) [ -z "$up" ] && up="." cd $up $command "$@"