chris@241: #!/bin/sh chris@241: chris@242: mirrordir="/var/mirror" Chris@433: hg="/usr/local/bin/hg" chris@242: chris@241: project="$1" chris@241: local_repo="$2" chris@241: remote_repo="$3" chris@241: chris@241: if [ -z "$project" ] || [ -z "$local_repo" ] || [ -z "$remote_repo" ]; then chris@241: echo "Usage: $0 " chris@241: exit 2 chris@241: fi chris@241: chris@241: # We need to handle different source repository types separately. chris@241: # chris@241: # The convert extension cannot convert directly from a remote git chris@241: # repo; we'd have to mirror to a local repo first. Incremental chris@241: # conversions do work though. The hg-git plugin will convert chris@241: # directly from remote repositories, but not via all schemes chris@241: # (e.g. https is not currently supported). It's probably easier to chris@241: # use git itself to clone locally and then convert or hg-git from chris@241: # there. chris@241: # chris@241: # We can of course convert directly from remote Subversion repos, chris@241: # but we need to keep track of that -- you can ask to convert into a chris@241: # repo that has already been used (for Mercurial) and it'll do so chris@241: # happily; we don't want that. chris@241: # chris@241: # Converting from a remote Hg repo should be fine! chris@241: # chris@241: # One other thing -- we can't actually tell the difference between chris@241: # the various SCM types based on URL alone. We have to try them chris@241: # (ideally in an order determined by a guess based on the URL) and chris@241: # see what happens. chris@241: chris@242: project_mirror="$mirrordir/$project" chris@242: mkdir -p "$project_mirror" chris@242: project_repo_mirror="$project_mirror/repo" chris@241: chris@242: # Some test URLs: chris@242: # chris@242: # http://aimc.googlecode.com/svn/trunk/ chris@242: # http://aimc.googlecode.com/svn/ chris@242: # http://vagar.org/git/flam chris@242: # https://github.com/wslihgt/IMMF0salience.git chris@242: # http://hg.breakfastquay.com/dssi-vst/ chris@242: # git://github.com/schacon/hg-git.git chris@242: # http://svn.drobilla.net/lad (externals!) chris@242: chris@242: # If we are importing from another distributed system, then our aim is chris@242: # to create either a Hg repo or a git repo at $project_mirror, which chris@242: # we can then pull from directly to the Hg repo at $local_repo (using chris@242: # hg-git, in the case of a git repo). chris@242: chris@242: # Importing from SVN, we should use hg convert directly to the target chris@242: # hg repo (or should we?) but keep a record of the last changeset ID chris@242: # we brought in, and test each time whether it matches the last chris@242: # changeset ID actually in the repo chris@242: chris@242: success="" chris@242: Chris@436: # If we have a record of the last successfully updated remote repo Chris@436: # URL, check it against our current remote URL: if it has changed, we Chris@436: # will need to start again with a new clone rather than pulling Chris@436: # updates into the existing local mirror Chris@436: Chris@436: successfile="$project_mirror/last_successful_url" Chris@436: if [ -f "$successfile" ]; then Chris@436: last=$(cat "$successfile") chris@437: if [ x"$last" = x"$remote_repo" ]; then Chris@436: echo "$$: Remote URL is unchanged from last successful update" Chris@436: else Chris@436: echo "$$: Remote URL has changed since last successful update:" Chris@436: echo "$$: Last URL was $last, current is $remote_repo" Chris@436: suffix="$$.$(date +%s)" Chris@436: echo "$$: Moving existing repos to $suffix suffix and starting afresh" Chris@436: mv "$project_repo_mirror" "$project_repo_mirror"."$suffix" Chris@436: mv "$local_repo" "$local_repo"."$suffix" Chris@436: mv "$successfile" "$successfile"."$suffix" chris@437: touch "$project_mirror/url_changed" Chris@436: fi Chris@436: fi Chris@436: chris@242: if [ -d "$project_repo_mirror" ]; then chris@242: chris@242: # Repo mirror exists: update it chris@242: echo "$$: Mirror for project $project exists at $project_repo_mirror, updating" 1>&2 chris@242: chris@242: if [ -d "$project_repo_mirror/.hg" ]; then Chris@433: "$hg" --config extensions.convert= convert --datesort "$remote_repo" "$project_repo_mirror" && success=true chris@439: if [ -z "$success" ]; then chris@439: ( cd "$project_repo_mirror" && "$hg" pull "$remote_repo" ) && success=true chris@439: fi chris@242: elif [ -d "$project_repo_mirror/.git" ]; then Chris@431: ( cd "$project_repo_mirror" && git pull "$remote_repo" master ) && success=true chris@242: else chris@242: echo "$$: ERROR: Repo mirror dir $project_repo_mirror exists but is not an Hg or git repo" 1>&2 chris@242: fi chris@242: chris@242: else chris@242: chris@242: # Repo mirror does not exist yet chris@242: echo "$$: Mirror for project $project does not yet exist at $project_repo_mirror, trying to convert or clone" 1>&2 chris@242: chris@242: case "$remote_repo" in chris@242: *git*) chris@242: git clone "$remote_repo" "$project_repo_mirror" || Chris@433: "$hg" --config extensions.convert= convert --datesort "$remote_repo" "$project_repo_mirror" chris@242: ;; chris@242: *) Chris@433: "$hg" --config extensions.convert= convert --datesort "$remote_repo" "$project_repo_mirror" || chris@299: git clone "$remote_repo" "$project_repo_mirror" || Chris@433: "$hg" clone "$remote_repo" "$project_repo_mirror" chris@242: ;; chris@242: esac && success=true chris@242: chris@242: fi chris@242: chris@242: echo "Success=$success" chris@242: chris@242: if [ -n "$success" ]; then chris@242: echo "$$: Update successful, pulling into local repo at $local_repo" Chris@436: if [ ! -d "$local_repo" ]; then Chris@436: "$hg" init "$local_repo" Chris@436: fi chris@242: if [ -d "$project_repo_mirror/.git" ]; then Chris@436: ( cd "$local_repo" && "$hg" --config extensions.hggit= pull "$project_repo_mirror" ) && echo "$remote_repo" > "$successfile" chris@242: else Chris@436: ( cd "$local_repo" && "$hg" pull "$project_repo_mirror" ) && echo "$remote_repo" > "$successfile" chris@242: fi chris@242: fi