summaryrefslogtreecommitdiff
path: root/exporters/darcs/git-darcs
blob: c4343ef887571ebd7b452d91b424e323ea950c69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#!/bin/bash
#
#   git-darcs - bidirectional operation between a darcs repo and git
#
#   Copyright (c) 2008, 2010 by Miklos Vajna <vmiklos@frugalware.org>
#
#   Based on git-bzr, which is
#
#   Copyright (c) 2008 Pieter de Bie <pdebie@ai.rug.nl>
#
#   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, see <http://www.gnu.org/licenses/>.
#

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 '/^</ p')" ]; then
		echo "Nothing to push. Commit something first"
		return 1
	fi
	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 "We do not have refmapping yet. Then how can I push?"
		return 1
	fi
	pre_push="$(git config git-darcs.$remote.pre-push)"
	if [ -n "$pre_push" ]; then
		$pre_push
	fi
	echo "Pushing the following updates:"
	git shortlog refs/remotes/darcs/$remote..
	git fast-export --import-marks=$git_map --export-marks=$git_map HEAD | \
		(cd $location; darcs-fast-import --import-marks=$darcs_map --export-marks=$darcs_map \
		--logfile $git_dir/darcs-git/push.log)
	if [ $? == 0 ]; then
		git update-ref refs/remotes/darcs/$remote HEAD
		post_push="$(git config git-darcs.$remote.post-push)"
		if [ -n "$post_push" ]; then
			$post_push
		fi
	fi
}

# List the darcs remotes
list()
{
	if [ -z "$*" ]
	then
		git config -l | sed -n -e '/git-darcs\..*/ {s/git-darcs\.//; s/\.location=.*//p}'
		return 0
	elif [ "$#" -eq 1 ]
	then
		case $1 in
			-v|--verbose)
				git config -l | sed -n -e '/git-darcs\..*/ {s/git-darcs\.//; s/\.location=/\t/p}'
				return 0
				;;
		esac
	fi
	echo "Usage: git darcs list [-v|--verbose]"
	return 1
}

# Find the darcs commit(s) supporting a git SHA1 prefix
find_darcs()
{
	sha1="$1"
	shift
	if [ -z "$sha1" -o -n "$*" ]
	then
		echo "Usage: git darcs find-darcs <sha1-prefix>"
		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 <patch-prefix>"
		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 "$@"