#!/bin/bash
# dev/vcs - Version Control System (VCS) Support
#
# This library provides an abstract interface to various kinds of
# version control systems, unifying them into a set of git repositories.
set -e
######
# Generic VCS Settings
dev_vcs_config_init() {
# $vcs_repo_kinds[] - Kinds of repositories presently supported.
#
# .. note:
# This could be moved to a plugin-based system.
lib_setting_arrays -ro vcs_repo_kinds
vcs_repo_kinds=( git svn hg bzr file www )
}
######
# VCS Package Specification
#
# A `VCS package specification` is encoded as the following tuple::
#
# <name>|<kind>|<url>
#
# where:
# * ``name`` is the local path name for the project file,
# * ``kind`` is the kind of VCS to use (see ``$vcs_repo_kinds[]``), and
# * ``url`` is the URL for retrieving the package.
# vcs_spec_build() - Prints a project specification for the named
# project ($1), repository kind ($2), and URL ($3).
vcs_spec_build() {
has_args 3 "$@"
echo "$1|$2|$3"
}
# with_vcs_spec() - Decomposes the given specification ($1) into its
# parts, passing them to the given command ($@).
with_vcs_spec() {
local spec=$1
shift
local -a args
args=( $(str_split '|' "$spec") )
"$@" "${args[@]}"
}
# vcs_spec_info() - Prints a human-readable version of the parts of a
# package specification ($1)
vcs_spec_info() { for_each _vcs_spec_info "$@"; }
_vcs_spec_info() { with_vcs_spec "$1" __vcs_spec_info; }
__vcs_spec_info() { echo "$1 ($2)"; echo -e "\t$3"; }
# vcs_spec_clone() - Clones project repositories from specifications ($@).
vcs_spec_clone() { for_each _vcs_spec_clone "$@"; }
_vcs_spec_clone() { with_vcs_spec "$1" vcs_repo_clone; }
# vcs_spec_update() - Updates project repositories from specifications ($@).
vcs_spec_update() { for_each _vcs_spec_clone "$@"; }
_vcs_spec_update() { with_vcs_spec "$1" __vcs_spec_update; }
__vcs_spec_update() { run_in_dir "$1" vcs_repo_update "$2"; }
######
# Generic Version Control
vcs_run() {
min_args 2 "$@"
local kind=$1
local cmd=$2
shift 2
local sym=$kind
case "$kind" in
(git) lib_load 'sys/tool/git' ;;
(git-svn) lib_load 'sys/tool/git-svn' ;;
(svn) lib_load 'sys/tool/svn' ;;
(hg|bzr|file|www)
error "$kind: backend unimplemented" ;;
(*)
error "$kind: unsupported repository" ;;
esac
sym=$(lib_symbol "$sym")
"${sym}_${cmd}" "$@"
}
######
# Project Management
vcs_repo_kind() {
if [ -d .git ]; then
echo 'git'
elif [ -d .svn ]; then
echo 'svn'
else
error "unknown repository kind"
fi
}
git_vcs_url() { git remote get-url origin; }
svn_vcs_url() { svn info |grep '^URL:' | cut -c6-; }
vcs_repo_url() {
local kind=$1
kind=${kind:-$(vcs_repo_kind)}
vcs_run "$kind" vcs_url
}
# vcs_repo_spec() - Prints a project specification for the named repository
# ($1), extracting the repository kind and URL from the current directory.
# $1 - Repository name
vcs_repo_spec() {
local name=$1
local kind url
kind=$(vcs_repo_kind)
url=$(vcs_repo_url "$kind")
vcs_spec_build "$name" "$kind" "$url"
}
# vcs_repo_clone() - Creates a local copy of a repository ($1) given its
# type ($2) and URL ($3).
vcs_repo_clone() {
has_args 3 "$@"
local name=$1
local kind=$2
local url=$3
if [ ! -d "$name" ]; then
vcs_run "$kind" clone "$url" "$name"
return
fi
local spec rspec
spec=$(vcs_spec_build "$@")
rspec=$(run_in_dir "$name" vcs_repo_spec "$name")
if [ "$spec" = "$rspec" ]; then
run_in_dir "$name" vcs_repo_update "$kind"
else
error "$name: specification changed\n$spec\n$rspec"
fi
}
vcs_repo_update() {
local kind=$1
kind=${kind:-$(vcs_repo_kind)}
vcs_run "$kind" update
}
Generated on Fri Jul 28 14:35:31 PDT 2017 by mcsh d14 v0.23.0.