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 # Remove any left-over svn-remote.svn config from a previous failed attempt
143 git config
--remove-section svn-remote.svn
2>/dev
/null ||
:
144 # Remove any left-over svn dir from a previous failed attempt
146 # We require svn info to succeed on the URL otherwise it's
147 # simply not a valid URL and without using -s on the init it
148 # will not otherwise be tested until the fetch
149 svn
--non-interactive info
"$svnurl" > /dev
/null
150 # We initially use -s for the init which will possibly shorten
151 # the URL. However, the shortening can fail if a password is
152 # not required for the longer version but is for the shorter,
153 # so try again without -s if the -s version fails.
154 # We must use GIT_DIR=. here or ever so "helpful" git-svn will
155 # create a .git subdirectory!
156 GIT_DIR
=. git svn init
--prefix "" -s "$svnurl" < /dev
/null || \
157 GIT_DIR
=. git svn init
--prefix "" "$svnurl" < /dev
/null
158 # We need to remember this url so we can detect changes because
159 # ever so "helpful" git-svn may shorten it!
160 config_set svnurl
"$svnurl"
161 # At this point, since we asked for a standard layout (-s) git-svn
162 # may have been "helpful" and adjusted our $svnurl to a prefix and
163 # then glued the removed suffix onto the front of any svn-remote.svn.*
164 # config items. We could avoid this by not using the '-s' option
165 # but then we might not get all the history. If, for example, we
166 # are cloning an http://svn.example.com/repos/public repository that
167 # early in its history moved trunk => public/trunk we would miss that
168 # earlier history without allowing the funky shorten+prefix behavior.
169 # So we read back the svn-remote.svn.fetch configuration and compute
170 # the prefix. This way we are sure to get the correct prefix.
171 gitsvnurl
="$(git config --get svn-remote.svn.url || :)"
172 gitsvnfetch
="$(git config --get-all svn-remote.svn.fetch | tail -1 || :)"
173 gitsvnprefix
="${gitsvnfetch%%:*}"
174 gitsvnsuffix
="${gitsvnprefix##*/}"
175 gitsvnprefix
="${gitsvnprefix%$gitsvnsuffix}"
176 # Ask git-svn to store everything in the normal non-remote
177 # locations being careful to use the correct prefix
178 git config
--replace-all svn-remote.svn.fetch
"${gitsvnprefix}trunk:refs/heads/master"
179 git config
--replace-all svn-remote.svn.branches
"${gitsvnprefix}branches/*:refs/heads/*"
180 git config
--replace-all svn-remote.svn.tags
"${gitsvnprefix}tags/*:refs/tags/*"
181 # look for additional non-standard directories to fetch
182 # check for standard layout at the same time
185 { svn
--non-interactive ls "$gitsvnurl/${gitsvnprefix}" 2>/dev
/null ||
:; } | \
186 { while read file; do case $file in
187 # skip the already-handled standard ones and any with a space or tab
189 trunk
/|branches
/|tags
/) foundstd
=1;;
190 # only fetch extra directories from the $svnurl root (not any files)
191 *?
/) git config
--add svn-remote.svn.fetch \
192 "${gitsvnprefix}${file%/}:refs/heads/${file%/}";;
195 # if files found and no standard directories present use a simpler layout
196 if [ -z "$foundstd" ] && [ -n "$foundfile" ]; then
197 git config
--unset svn-remote.svn.branches
198 git config
--unset svn-remote.svn.tags
199 git config
--replace-all svn-remote.svn.fetch
':refs/heads/master'
201 # Again, be careful to use GIT_DIR=. here or else new .git subdirectory!
202 GIT_DIR
=. git svn fetch
--quiet < /dev
/null
203 # git svn does not preserve group permissions in the svn subdirectory
204 chmod -R ug
+rw
,o
+r svn
205 # git svn also leaves behind ref turds that end with @nnn
206 # We get rid of them now
208 { while read sha1 ref
; do
210 ?
*@
[1-9]|?
*@
[1-9][0-9]|?
*@
[1-9][0-9][0-9]|?
*@
[1-9][0-9][0-9][0-9]|\
211 ?
*@
[1-9][0-9][0-9][0-9][0-9]|?
*@
[1-9][0-9][0-9][0-9][0-9][0-9]|\
212 ?
*@
[1-9][0-9][0-9][0-9][0-9][0-9][0-9]|\
213 ?
*@
[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
214 git update-ref
-d "$ref"
219 [ -n "$cfg_mirror_darcs" ] ||
{ echo "Mirroring darcs is disabled" >&2; exit 1; }
220 httpurl
="http://${url#darcs://}"
221 # Remove any left-over .darcs dirs from a previous failed attempt
223 # Remove any left-over export files from a previous failed attempt
224 rm -f dfe-marks gfi-marks gfi-packs
225 git_darcs_fetch
"$httpurl"
228 [ -n "$cfg_mirror_bzr" ] ||
{ echo "Mirroring bzr is disabled" >&2; exit 1; }
229 # we just remove bzr:// here, a typical bzr url is just
231 bzrurl
="${url#bzr://}"
232 # Remove any left-over export files from a previous failed attempt
233 rm -f bfe-marks gfi-marks gfi-packs
234 git_bzr_fetch
"$bzrurl"
236 hg
+http
://* | hg
+https
://*)
237 [ -n "$cfg_mirror_hg" ] ||
{ echo "Mirroring hg is disabled" >&2; exit 1; }
238 # We just remove hg+ here, so hg+http://... becomes http://...
240 # Remove any left-over repo.hg dir from a previous failed attempt
242 # Remove any left-over export files from a previous failed attempt
243 rm -f gfi-packs hg2git-heads hg2git-mapping hg2git-marks
* hg2git-state
244 # Perform the initial hg clone
245 hg clone
-U "$hgurl" "$(pwd)/repo.hg"
246 # Do the fast-export | fast-import
250 git remote
rm origin
>/dev
/null
2>&1 ||
:
251 # starting with Git 1.7.5 --mirror by itself will spew a warning
252 # since we support older Git versions, just toss the warning
253 git remote add
--mirror origin
"$url" 2>/dev
/null
254 # Set the correct HEAD symref by using ls-remote first
255 GIT_SSL_NO_VERIFY
=1 GIT_TRACE_PACKET
=1 git ls-remote origin
>.refs-temp
2>.pkts-temp || \
257 # Since everything was redirected, on failure there'd be no output,
258 # so let's make some failure output
261 echo "git ls-remote \"$url\" failed"
264 # Compensate for git() {} side effects
265 unset GIT_TRACE_PACKET
266 # If the server is running at least Git 1.8.4.3 then it will send us the actual
267 # symref for HEAD. If we are running at least Git 1.7.5 then we can snarf that
268 # out of the packet trace data.
269 if [ -s .refs-temp
]; then
270 # Nothing to do unless the remote repository has at least 1 ref
271 # See if we got a HEAD ref
272 head="$(grep -E "^
$octet20[[:space
:]]+HEAD\$
" <.refs-temp | awk '{print $1}')"
273 # If the remote has HEAD set to a symbolic ref that does not exist
274 # then we will not receive a HEAD ref in the ls-remote output
278 if [ -n "$head" ]; then
279 symrefcap
="$(sed -ne <.pkts-temp \
280 '/packet:.*git<.*[[:space:]]symref=HEAD:refs\/heads\/[^[:space:]][^[:space:]]*/'"\
281 "'{s/^.*[[:space:]]symref=HEAD:\(refs\/heads\/[^[:space:]][^[:space:]]*\).*$/\1/;p;}')"
282 # prefer $symrefcap (refs/heads/master if no $symrefcap) if it
283 # matches HEAD otherwise take the first refs/heads/... match
286 [ -n "$ref" ] ||
continue
287 matchcnt
=$
(( $matchcnt + 1 ))
288 if [ -z "$headref" ] ||
[ "$ref" = "${symrefcap:-refs/heads/master}" ]; then
291 [ "$headref" = "${symrefcap:-refs/heads/master}" -a $matchcnt -gt 1 ] && break
293 $(grep -E "^$head[[:space:]]+refs/heads/[^[:space:]]+\$" <.refs-temp | \
296 # Warn if there was more than one match and $symrefcap is empty
297 # or $symrefcap is not the same as $headref since our choice might
298 # differ from the source repository's HEAD
299 if [ $matchcnt -ge 1 -a "$symrefcap" != "$headref" ] && \
300 [ -n "$symrefcap" -o $matchcnt -gt 1 ]; then
304 if [ -z "$headref" ]; then
305 # If we still don't have a HEAD ref then prefer refs/heads/master
306 # if it exists otherwise take the first refs/heads/...
307 # We do not support having a detached HEAD.
308 # We always warn now because we will be setting HEAD differently
309 # than the source repository had HEAD set
312 [ -n "$ref" ] ||
continue
313 if [ -z "$headref" ] ||
[ "$ref" = "refs/heads/master" ]; then
316 [ "$headref" = "refs/heads/master" ] && break
318 $(grep -E "^$octet20[[:space:]]+refs/heads/[^[:space:]]+\$" <.refs-temp | \
322 # If we STILL do not have a HEAD ref (perhaps the source repository
323 # contains only tags) then use refs/heads/master. It will be invalid
324 # but is no worse than we used to do by default and we'll warn about
325 # it. We do not support a HEAD symref to anything other than refs/heads/...
326 [ -n "$headref" ] || headref
="refs/heads/master"
327 git symbolic-ref HEAD
"$headref"
328 GIT_SSL_NO_VERIFY
=1 git remote update
329 GIT_SSL_NO_VERIFY
=1 git remote prune origin
332 git symbolic-ref HEAD
"refs/heads/master"
334 rm -f .refs-temp .pkts-temp
338 # The objects subdirectories permissions must be updated now.
339 # In the case of a dumb http clone, the permissions will not be correct
340 # (missing group write) despite the core.sharedrepository=1 setting!
341 # The objects themselves seem to have the correct permissions.
342 # This problem appears to have been fixed in the most recent git versions.
344 [ "$cfg_permission_control" != "Hooks" ] || perms
=go
+w
345 chmod $perms $
(find objects
-maxdepth 1 -type d
) 2>/dev
/null ||
:
347 # Initialize gitweb.lastreceive, gitweb.lastchange and info/lastactivity
348 git config gitweb.lastreceive
"$(date '+%a, %d %b %Y %T %z')"
349 git config gitweb.lastchange
"$(date '+%a, %d %b %Y %T %z')"
350 git for-each-ref
--sort=-committerdate --format='%(committerdate:iso8601)' \
351 --count=1 refs
/heads
> info
/lastactivity
352 [ -s info
/lastactivity
] ||
rm -f info
/lastactivity
355 echo "Final touches..."
356 git update-server-info
360 [ -z "$warnempty" ] ||
362 WARNING: You have mirrored an empty repository.
365 [ -n "$showheadwarn" -a -n "$headref" ] &&
367 NOTE: HEAD has been set to a symbolic ref to \"$headref\".
368 Use the \"Project settings\" link to choose a different HEAD symref.
373 NOTE: Since this is a mirror of a non-Git source, the initial repository
374 size may be somewhat larger than necessary. This will be corrected
375 shortly. If you intend to clone this repository you may want to
376 wait up to 1 hour before doing so in order to receive the more
379 [ -z "$mailaddrs" ] ||
380 mail -s "[$cfg_name] $proj clone completed" "$mailaddrs" <<EOT || :
381 Congratulations! The clone of project $proj just completed.
384 * GitWeb interface: $cfg_gitweburl/$projdir
385 * Project settings: $cfg_webadmurl/editproj.cgi?name=$(echo "$proj" | sed -e 's/[+]/%2B/g')
386 $emptynote$headnote$sizenote
390 echo "Mirroring finished successfuly!"
391 # In case this is a re-mirror, lastgc could have been set already so clear it now
392 git config
--unset gitweb.lastgc ||
:
393 rm .clone_in_progress
394 echo "$sizenote@OVER@"