3 # Invoked from taskd/taskd.pl
7 # darcs fast-export | git fast-import with error handling
13 { read -r _err1 ||
:; read -r _err2 ||
:; } <<-EOT
15 exec 4>&3 3>&1 1>&4 4>&-
18 "$cfg_basedir"/bin/darcs-fast-export \
19 --export-marks="$(pwd)/dfe-marks" "$1" 3>&- || _e1=$?
25 --export-marks="$(pwd)/gfi-marks" \
26 --export-pack-edges="$(pwd)/gfi-packs" \
27 --force 3>&- || _e2=$?
33 [ "$_err1" = 0 -a "$_err2" = 0 ]
37 # bzr fast-export | git fast-import with error handling
43 { read -r _err1 ||
:; read -r _err2 ||
:; } <<-EOT
45 exec 4>&3 3>&1 1>&4 4>&-
49 --export-marks="$(pwd)/bfe-marks" "$1" 3>&- || _e1=$?
55 --export-marks="$(pwd)/gfi-marks" \
56 --export-pack-edges="$(pwd)/gfi-packs" \
57 --force 3>&- || _e2=$?
63 [ "$_err1" = 0 -a "$_err2" = 0 ]
69 # We must now close the .clonelog file that is open on stdout and stderr
71 failaddrs
="$(config_get owner || :)"
72 [ -z "$cfg_admincc" -o "$cfg_admincc" = "0" -o -z "$cfg_admin" ] || \
73 if [ -z "$failaddrs" ]; then failaddrs
="$cfg_admin"; else failaddrs
="$failaddrs,$cfg_admin"; fi
74 [ -z "$failaddrs" ] || \
77 Condolences. The clone of project $proj just failed.
80 * Project settings: $cfg_webadmurl/editproj.cgi?name=$(echo "$proj" | sed -e 's/[+]/%2B/g')
82 The project settings link may be used to adjust the settings
83 and restart the clone in order to try the clone again.
85 if [ -f .clonelog
-a -r .clonelog
]; then
89 loglines
=$
(wc -l <.clonelog
)
90 if [ $loglines -le 203 ]; then
95 echo "[ ... elided $(( $loglines - 200 )) middle lines ... ]"
100 } |
mail -s "[$cfg_name] $proj clone failed" "$failaddrs" ||
:
106 [ "$cfg_permission_control" != "Hooks" ] ||
umask 000
109 proj
="${projdir%.git}"
111 cd "$cfg_reporoot/$projdir"
112 trap "echo '@OVER@'; touch .clone_failed; send_clone_failed" EXIT
113 [ -n "$cfg_mirror" ] ||
{ echo "Mirroring is disabled" >&2; exit 1; }
114 url
="$(config_get baseurl || :)"
115 case "$url" in *" "*|
*" "*|
"")
116 echo "Bad mirror URL (\"$url\")"
119 echo "Mirroring from URL \"$url\""
122 if [ "$cfg_project_owners" = "source" ]; then
123 config_set owner
"$(stat -c %U "$url" 2>/dev/null)"
126 mailaddrs
="$(config_get owner || :)"
127 [ -z "$cfg_admin" ] || \
128 if [ -z "$mailaddrs" ]; then mailaddrs
="$cfg_admin"; else mailaddrs
="$mailaddrs,$cfg_admin"; fi
131 echo "Initiating mirroring..."
136 svn
://* | svn
+http
://* | svn
+https
://*)
137 [ -n "$cfg_mirror_svn" ] ||
{ echo "Mirroring svn is disabled" >&2; exit 1; }
138 # We just remove svn+ here, so svn+http://... becomes http://...
139 # We also remove a trailing '/' to match what git-svn will do
142 # We require svn info to succeed on the URL otherwise it's
143 # simply not a valid URL and without using -s on the init it
144 # will not otherwise be tested until the fetch
145 svn
--non-interactive info
"$svnurl" > /dev
/null
146 # We initially use -s for the init which will possibly shorten
147 # the URL. However, the shortening can fail if a password is
148 # not required for the longer version but is for the shorter,
149 # so try again without -s if the -s version fails.
150 # We must use GIT_DIR=. here or ever so "helpful" git-svn will
151 # create a .git subdirectory!
152 GIT_DIR
=. git svn init
--prefix "" -s "$svnurl" < /dev
/null || \
153 GIT_DIR
=. git svn init
--prefix "" "$svnurl" < /dev
/null
154 # We need to remember this url so we can detect changes because
155 # ever so "helpful" git-svn may shorten it!
156 config_set svnurl
"$svnurl"
157 # At this point, since we asked for a standard layout (-s) git-svn
158 # may have been "helpful" and adjusted our $svnurl to a prefix and
159 # then glued the removed suffix onto the front of any svn-remote.svn.*
160 # config items. We could avoid this by not using the '-s' option
161 # but then we might not get all the history. If, for example, we
162 # are cloning an http://svn.example.com/repos/public repository that
163 # early in its history moved trunk => public/trunk we would miss that
164 # earlier history without allowing the funky shorten+prefix behavior.
165 # So we read back the svn-remote.svn.fetch configuration and compute
166 # the prefix. This way we are sure to get the correct prefix.
167 gitsvnurl
="$(git config --get svn-remote.svn.url || :)"
168 gitsvnfetch
="$(git config --get-all svn-remote.svn.fetch | tail -1 || :)"
169 gitsvnprefix
="${gitsvnfetch%%:*}"
170 gitsvnsuffix
="${gitsvnprefix##*/}"
171 gitsvnprefix
="${gitsvnprefix%$gitsvnsuffix}"
172 # Ask git-svn to store everything in the normal non-remote
173 # locations being careful to use the correct prefix
174 git config
--replace-all svn-remote.svn.fetch
"${gitsvnprefix}trunk:refs/heads/master"
175 git config
--replace-all svn-remote.svn.branches
"${gitsvnprefix}branches/*:refs/heads/*"
176 git config
--replace-all svn-remote.svn.tags
"${gitsvnprefix}tags/*:refs/tags/*"
177 # look for additional non-standard directories to fetch
178 # check for standard layout at the same time
181 { svn
--non-interactive ls "$gitsvnurl/${gitsvnprefix}" 2>/dev
/null ||
:; } | \
182 { while read file; do case $file in
183 # skip the already-handled standard ones and any with a space or tab
185 trunk
/|branches
/|tags
/) foundstd
=1;;
186 # only fetch extra directories from the $svnurl root (not any files)
187 *?
/) git config
--add svn-remote.svn.fetch \
188 "${gitsvnprefix}${file%/}:refs/heads/${file%/}";;
191 # if files found and no standard directories present use a simpler layout
192 if [ -z "$foundstd" ] && [ -n "$foundfile" ]; then
193 git config
--unset svn-remote.svn.branches
194 git config
--unset svn-remote.svn.tags
195 git config
--replace-all svn-remote.svn.fetch
':refs/heads/master'
197 # Again, be careful to use GIT_DIR=. here or else new .git subdirectory!
198 GIT_DIR
=. git svn fetch
--quiet < /dev
/null
199 # git svn does not preserve group permissions in the svn subdirectory
200 chmod -R ug
+rw
,o
+r svn
201 # git svn also leaves behind ref turds that end with @nnn
202 # We get rid of them now
204 { while read sha1 ref
; do
206 ?
*@
[1-9]|?
*@
[1-9][0-9]|?
*@
[1-9][0-9][0-9]|?
*@
[1-9][0-9][0-9][0-9]|\
207 ?
*@
[1-9][0-9][0-9][0-9][0-9]|?
*@
[1-9][0-9][0-9][0-9][0-9][0-9]|\
208 ?
*@
[1-9][0-9][0-9][0-9][0-9][0-9][0-9]|\
209 ?
*@
[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
210 git update-ref
-d "$ref"
215 [ -n "$cfg_mirror_darcs" ] ||
{ echo "Mirroring darcs is disabled" >&2; exit 1; }
216 httpurl
="http://${url#darcs://}"
217 # Remove any left-over .darcs dirs from a previous failed attempt
219 # Remove any left-over export files from a previous failed attempt
220 rm -f dfe-marks gfi-marks gfi-packs
221 git_darcs_fetch
"$httpurl"
224 [ -n "$cfg_mirror_bzr" ] ||
{ echo "Mirroring bzr is disabled" >&2; exit 1; }
225 # we just remove bzr:// here, a typical bzr url is just
227 bzrurl
="${url#bzr://}"
228 # Remove any left-over export files from a previous failed attempt
229 rm -f bfe-marks gfi-marks gfi-packs
230 git_bzr_fetch
"$bzrurl"
232 hg
+http
://* | hg
+https
://*)
233 [ -n "$cfg_mirror_hg" ] ||
{ echo "Mirroring hg is disabled" >&2; exit 1; }
234 # We just remove hg+ here, so hg+http://... becomes http://...
236 # Remove any left-over repo.hg dir from a previous failed attempt
238 # Remove any left-over export files from a previous failed attempt
239 rm -f gfi-packs hg2git-heads hg2git-mapping hg2git-marks
* hg2git-state
240 # Perform the initial hg clone
241 hg clone
-U "$hgurl" "$(pwd)/repo.hg"
242 # Do the fast-export | fast-import
246 git remote
rm origin
>/dev
/null
2>&1 ||
:
247 # starting with Git 1.7.5 --mirror by itself will spew a warning
248 # since we support older Git versions, just toss the warning
249 git remote add
--mirror origin
"$url" 2>/dev
/null
250 # Set the correct HEAD symref by using ls-remote first
251 GIT_SSL_NO_VERIFY
=1 GIT_TRACE_PACKET
=1 git ls-remote origin
>.refs-temp
2>.pkts-temp || \
253 # Since everything was redirected, on failure there'd be no output,
254 # so let's make some failure output
257 echo "git ls-remote \"$url\" failed"
260 # Compensate for git() {} side effects
261 unset GIT_TRACE_PACKET
262 # If the server is running at least Git 1.8.4.3 then it will send us the actual
263 # symref for HEAD. If we are running at least Git 1.7.5 then we can snarf that
264 # out of the packet trace data.
265 if [ -s .refs-temp
]; then
266 # Nothing to do unless the remote repository has at least 1 ref
267 # See if we got a HEAD ref
268 head="$(grep -E "^
$octet20[[:space
:]]+HEAD\$
" <.refs-temp | awk '{print $1}')"
269 # If the remote has HEAD set to a symbolic ref that does not exist
270 # then we will not receive a HEAD ref in the ls-remote output
274 if [ -n "$head" ]; then
275 symrefcap
="$(sed -ne <.pkts-temp \
276 '/packet:.*git<.*[[:space:]]symref=HEAD:refs\/heads\/[^[:space:]][^[:space:]]*/'"\
277 "'{s/^.*[[:space:]]symref=HEAD:\(refs\/heads\/[^[:space:]][^[:space:]]*\).*$/\1/;p;}')"
278 # prefer $symrefcap (refs/heads/master if no $symrefcap) if it
279 # matches HEAD otherwise take the first refs/heads/... match
282 [ -n "$ref" ] ||
continue
283 matchcnt
=$
(( $matchcnt + 1 ))
284 if [ -z "$headref" ] ||
[ "$ref" = "${symrefcap:-refs/heads/master}" ]; then
287 [ "$headref" = "${symrefcap:-refs/heads/master}" -a $matchcnt -gt 1 ] && break
289 $(grep -E "^$head[[:space:]]+refs/heads/[^[:space:]]+\$" <.refs-temp | \
292 # Warn if there was more than one match and $symrefcap is empty
293 # or $symrefcap is not the same as $headref since our choice might
294 # differ from the source repository's HEAD
295 if [ $matchcnt -ge 1 -a "$symrefcap" != "$headref" ] && \
296 [ -n "$symrefcap" -o $matchcnt -gt 1 ]; then
300 if [ -z "$headref" ]; then
301 # If we still don't have a HEAD ref then prefer refs/heads/master
302 # if it exists otherwise take the first refs/heads/...
303 # We do not support having a detached HEAD.
304 # We always warn now because we will be setting HEAD differently
305 # than the source repository had HEAD set
308 [ -n "$ref" ] ||
continue
309 if [ -z "$headref" ] ||
[ "$ref" = "refs/heads/master" ]; then
312 [ "$headref" = "refs/heads/master" ] && break
314 $(grep -E "^$octet20[[:space:]]+refs/heads/[^[:space:]]+\$" <.refs-temp | \
318 # If we STILL do not have a HEAD ref (perhaps the source repository
319 # contains only tags) then use refs/heads/master. It will be invalid
320 # but is no worse than we used to do by default and we'll warn about
321 # it. We do not support a HEAD symref to anything other than refs/heads/...
322 [ -n "$headref" ] || headref
="refs/heads/master"
323 git symbolic-ref HEAD
"$headref"
324 GIT_SSL_NO_VERIFY
=1 git remote update
325 GIT_SSL_NO_VERIFY
=1 git remote prune origin
328 git symbolic-ref HEAD
"refs/heads/master"
330 rm -f .refs-temp .pkts-temp
334 # The objects subdirectories permissions must be updated now.
335 # In the case of a dumb http clone, the permissions will not be correct
336 # (missing group write) despite the core.sharedrepository=1 setting!
337 # The objects themselves seem to have the correct permissions.
338 # This problem appears to have been fixed in the most recent git versions.
340 [ "$cfg_permission_control" != "Hooks" ] || perms
=go
+w
341 chmod $perms $
(find objects
-maxdepth 1 -type d
) 2>/dev
/null ||
:
343 # Initialize gitweb.lastreceive, gitweb.lastchange and info/lastactivity
344 git config gitweb.lastreceive
"$(date '+%a, %d %b %Y %T %z')"
345 git config gitweb.lastchange
"$(date '+%a, %d %b %Y %T %z')"
346 git for-each-ref
--sort=-committerdate --format='%(committerdate:iso8601)' \
347 --count=1 refs
/heads
> info
/lastactivity
348 [ -s info
/lastactivity
] ||
rm -f info
/lastactivity
351 echo "Final touches..."
352 git update-server-info
356 [ -z "$warnempty" ] ||
358 WARNING: You have mirrored an empty repository.
361 [ -n "$showheadwarn" -a -n "$headref" ] &&
363 NOTE: HEAD has been set to a symbolic ref to \"$headref\".
364 Use the \"Project settings\" link to choose a different HEAD symref.
369 NOTE: Since this is a mirror of a non-Git source, the initial repository
370 size may be somewhat larger than necessary. This will be corrected
371 shortly. If you intend to clone this repository you may want to
372 wait up to 1 hour before doing so in order to receive the more
375 [ -z "$mailaddrs" ] ||
376 mail -s "[$cfg_name] $proj clone completed" "$mailaddrs" <<EOT || :
377 Congratulations! The clone of project $proj just completed.
380 * GitWeb interface: $cfg_gitweburl/$projdir
381 * Project settings: $cfg_webadmurl/editproj.cgi?name=$(echo "$proj" | sed -e 's/[+]/%2B/g')
382 $emptynote$headnote$sizenote
386 echo "Mirroring finished successfuly!"
387 # In case this is a re-mirror, lastgc could have been set already so clear it now
388 git config
--unset gitweb.lastgc ||
:
389 rm .clone_in_progress
390 echo "$sizenote@OVER@"