~ubuntu-branches/ubuntu/trusty/cloud-utils/trusty-updates

« back to all changes in this revision

Viewing changes to bin/vcs-run

  • Committer: Package Import Robot
  • Author(s): Scott Moser
  • Date: 2013-06-19 11:59:32 UTC
  • Revision ID: package-import@ubuntu.com-20130619115932-pqawhq6i50u51xcm
Tags: 0.27-0ubuntu2
* sync to trunk at revno 230
  * ubuntu-cloudimg-query: change default release to 'precise'
  * growpart: fix some issues in error path reporting
  * growpart: capture output of 'partx --help' as older versions
    do not support that flag, and send output to stderr.
  * add 'vcs-run' utility for easily executing / bootstrapping
    from a version control system (hg, git, bzr)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
set -f
 
3
 
 
4
VERBOSITY=0
 
5
SUPPORTED_VCS="bzr hg git url"
 
6
RET_UNCLAIMED=3
 
7
RET_SUCCESS=0
 
8
RET_FAIL=1
 
9
DEF_COMMAND="vcs_run"
 
10
 
 
11
Usage() {
 
12
        cat <<EOF
 
13
Usage: ${0##*/} [ options ] repo-url [command [arguments]]
 
14
 
 
15
   obtain repository from repo-url, and execute 'command' with 'arguments'
 
16
 
 
17
   Command will default to '$DEF_COMMAND' in the top level of the repository.
 
18
 
 
19
   options:
 
20
      -t | --target  DIR   checkout branch to DIR [./(basename repo)]
 
21
           --vcs-type  V   repo-url is of type 'V' [auto]
 
22
                           supported: auto $SUPPORTED_VCS
 
23
      -v | --verbose       increase verbosity
 
24
      -D | --deps          attempt to install dependencies if necessary
 
25
EOF
 
26
}
 
27
 
 
28
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
 
29
error() { echo "$@" 1>&2; }
 
30
debug() {
 
31
        local level=${1}; shift;
 
32
        [ "${level}" -gt "${VERBOSITY}" ] && return
 
33
        error "${@}"
 
34
}
 
35
 
 
36
has_cmd() {
 
37
        command -v "$1" >/dev/null 2>&1
 
38
}
 
39
 
 
40
get_cmd() {
 
41
        # get_cmd(cmd, get_deps, packages)
 
42
        #   get command 'cmd' if necessary by installing 'packages'
 
43
        #   if 'get_deps' is false, then return error.
 
44
        local cmd="$1" deps="$2"
 
45
        shift 2
 
46
        has_cmd "$1" && return 0
 
47
        $deps || { error "No cmd '$cmd', but nodeps specified"; return 1; }
 
48
        apt_install "$@"
 
49
}
 
50
 
 
51
apt_install() {
 
52
        local cmd=""
 
53
        cmd=( env DEBIAN_FRONTEND=noninteractive apt-get --quiet 
 
54
                  --assume-yes install "$@" )
 
55
        [ "$(id -u)" = "0" ] ||
 
56
                cmd=( sudo "${cmd[@]}" )
 
57
        debug 1 "installing dependencies:" "${cmd[@]}"
 
58
        "${cmd[@]}"
 
59
}
 
60
 
 
61
vcsget_bzr() {
 
62
        # deps type src target cmd
 
63
        local deps="$1" rtype="$2" src="$3" target="$4" tmp=""
 
64
        if [ "$rtype" = "auto" ]; then
 
65
                case "$src" in
 
66
                        *.bzr|bzr:*|lp:*) :;;
 
67
                        *)
 
68
                                if ! [ -d "$src" -a -d "$src/.bzr" ]; then
 
69
                                        return $RET_UNCLAIMED
 
70
                                fi
 
71
                                src=$(cd "$src" && pwd) || return $RET_FAIL
 
72
                                ;;
 
73
                esac
 
74
        fi
 
75
        get_cmd bzr "$deps" bzr || return $RET_FAIL
 
76
        if [ -z "$target" ]; then
 
77
                tmp="${src##*/}"
 
78
                target="${tmp%.bzr}"
 
79
        fi
 
80
        local cmd="" q="--quiet"
 
81
        [ $VERBOSITY -gt 1 ] && q=""
 
82
 
 
83
        if [ -d "$target/.bzr" ]; then
 
84
                debug 1 "updating $target: bzr pull ${q:+$q }$src"
 
85
                ( cd "$target" && bzr pull $q "$src" )
 
86
        else
 
87
                debug 1 "branching to $target: bzr branch ${q:+$q }$src"
 
88
                bzr branch $q "$src" "$target"
 
89
        fi
 
90
        [ $? -eq 0 ] || return $RET_FAIL
 
91
        _RET="$target"
 
92
        return 0
 
93
}
 
94
 
 
95
vcsget_git() {
 
96
        # deps type src target cmd
 
97
        local deps="$1" rtype="$2" src="$3" target="$4" tmp=""
 
98
        if [ "$rtype" = "auto" ]; then
 
99
                case "$src" in
 
100
                        *.git|git:*) :;;
 
101
                        *)
 
102
                                if ! [ -d "$src" -a -d "$src/.git" ]; then
 
103
                                        return $RET_UNCLAIMED
 
104
                                fi
 
105
                                src=$(cd "$src" && pwd) || return $RET_FAIL
 
106
                                ;;
 
107
                esac
 
108
        fi
 
109
        get_cmd git "$deps" git || return $RET_FAIL
 
110
        if [ -z "$target" ]; then
 
111
                tmp="${src##*/}"
 
112
                target="${tmp%.git}"
 
113
        fi
 
114
        local q="--quiet"
 
115
        [ $VERBOSITY -gt 1 ] && q=""
 
116
        if [ -d "$target/.git" ]; then
 
117
                debug 1 "updating $target: git pull ${q:+$q }${src}"
 
118
                ( cd "$target" && git pull $q "$src" )
 
119
        else
 
120
                debug 1 "cloning to $target: git clone ${q:+$q }$src $target"
 
121
                git clone $q "$src" "$target" || return $RET_FAIL
 
122
        fi
 
123
        [ $? -eq 0 ] || return $RET_FAIL
 
124
        _RET="$target"
 
125
        return 0
 
126
}
 
127
 
 
128
vcsget_hg() {
 
129
        # deps type src target cmd
 
130
        local deps="$1" rtype="$2" src="$3" target="$4" tmp=""
 
131
        if [ "$rtype" = "auto" ]; then
 
132
                case "$src" in
 
133
                        *.hg|hg:*) :;;
 
134
                        *) return $RET_UNCLAIMED;;
 
135
                esac
 
136
        fi
 
137
        get_cmd hg "$deps" mercurial || return $RET_FAIL
 
138
        if [ -z "$target" ]; then
 
139
                tmp="${src##*/}"
 
140
                target="${tmp%.hg}"
 
141
        fi
 
142
        local quiet="--quiet"
 
143
        [ $VERBOSITY -gt 1 ] && quiet=""
 
144
        hg clone $quiet "$src" "$target" || return $RET_FAIL
 
145
        _RET="$target"
 
146
        return 0
 
147
}
 
148
 
 
149
vcsget_url() {
 
150
        # deps type src target cmd
 
151
        # if target is not specified, target directory is md5sum
 
152
        # of the url.  If cmd does not start with a /, then use it
 
153
        # as the output filename.  If it does start with a /, then
 
154
        # store the url in DEF_COMMAND in this directory.
 
155
        local deps="$1" rtype="$2" src="$3" target="$4" cmd="$5" tmp=""
 
156
        if [ "$rtype" = "auto" ]; then
 
157
                case "$src" in
 
158
                        http://*|https://*) :;;
 
159
                        *) return $RET_UNCLAIMED;;
 
160
                esac
 
161
        fi
 
162
        get_cmd wget "$deps" wget || return $RET_FAIL
 
163
        if [ -z "$target" ]; then
 
164
                target=$(echo "$src" | md5sum)
 
165
                target=${target%  -}
 
166
        fi
 
167
 
 
168
        local cmdname="$cmd"
 
169
        if [ "${cmd#/}" != "$cmd" ]; then
 
170
                cmdname="./$DEF_COMMAND"
 
171
        fi
 
172
 
 
173
        local quiet="--quiet"
 
174
        [ $VERBOSITY -gt 1 ] && quiet=""
 
175
 
 
176
        mkdir -p "$target" ||
 
177
                { error "failed mkdir -p '$target'"; return $RET_FAIL; }
 
178
        debug 1 "wget -O '$target/$cmdname' '$src'"
 
179
        wget $quiet -O "$target/$cmdname" "$src" || {
 
180
                error "failed wget -O '$target/$cmdname' '$src'"
 
181
                return $RET_FAIL
 
182
        }
 
183
        
 
184
        _RET="$target"
 
185
        return 0
 
186
}
 
187
 
 
188
main() {
 
189
        local short_opts="hDt:v"
 
190
        local long_opts="help,deps:,target:,vcs-type:,verbose"
 
191
        local getopt_out=$(getopt --name "${0##*/}" \
 
192
                --options "${short_opts}" --long "${long_opts}" -- "$@") &&
 
193
                eval set -- "${getopt_out}" ||
 
194
                { bad_Usage; return; }
 
195
 
 
196
        local cur="" next="" target="" rtype="auto" tmp=""
 
197
        local def_target="" deps="" getdeps=false arg0=""
 
198
 
 
199
        while [ $# -ne 0 ]; do
 
200
                cur="$1"; next="$2";
 
201
                case "$cur" in
 
202
                        -h|--help) Usage ; exit 0;;
 
203
                        -D|--deps) getdeps=true;;
 
204
                        -t|--target) target=$next; shift;;
 
205
                           --vcs-type) rtype=$next; shift;;
 
206
                        -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
 
207
                        --) shift; break;;
 
208
                esac
 
209
                shift;
 
210
        done
 
211
 
 
212
        [ $# -gt 0 ] || { bad_Usage "must provide at least repo"; return; }
 
213
 
 
214
        src_repo="$1"
 
215
        shift
 
216
        [ -n "$src_repo" ] || { error "empty source repo?"; return 1; }
 
217
 
 
218
        if [ -n "$target" ]; then
 
219
                tmp=$(dirname "${target}")
 
220
                [ -d "$tmp" ] || mkdir -p "$tmp" ||
 
221
                        { error "failed to create $tmp for '$target'"; return 1; }
 
222
        fi
 
223
 
 
224
        if [ $# -eq 0 ]; then
 
225
                set -- "$DEF_COMMAND"
 
226
        fi
 
227
        arg0="$1"
 
228
 
 
229
        local vcs vcslist="${SUPPORTED_VCS}"
 
230
        [ "$rtype" = "auto" ] || vcslist="$rtype"
 
231
 
 
232
        local workd=""
 
233
        for vcs in $vcslist; do
 
234
                has_cmd "vcsget_$vcs" ||
 
235
                        { error "unknown vcs type '$vcs'"; return 1; }
 
236
                "vcsget_$vcs" "$getdeps" "$rtype" "$src_repo" "$target" "$arg0"
 
237
                ret=$?
 
238
                case "$ret" in
 
239
                        $RET_UNCLAIMED) :;; # not claimed
 
240
                        $RET_SUCCESS) workd="$_RET"; break;;
 
241
                        *) error "failed to get '$src_repo' of type '$vcs'";
 
242
                                return $ret;;
 
243
                esac
 
244
        done
 
245
 
 
246
        [ -d "$workd" ] ||
 
247
                { error "unknown source repo '$src_repo'"; return 1; }
 
248
 
 
249
        cd "$workd" ||
 
250
                { error "failed to enter target dir '$workd'"; return 1; }
 
251
 
 
252
        if [ -f "./$1" ]; then
 
253
                if [ ! -x "./$1" ]; then
 
254
                        debug 1 "adding execute to ./$1"
 
255
                        chmod ugo+x "./$1" ||
 
256
                                { error "failed add execute to ./$1"; return 1; }
 
257
                fi
 
258
                tmp="./$1"
 
259
                shift
 
260
                set -- "$tmp" "$@"
 
261
        elif ! has_cmd "$1"; then
 
262
                error "command '$1' not available anywhere"
 
263
                return 1
 
264
        fi
 
265
 
 
266
        debug 1 "executing command in $PWD:" "$@"
 
267
        exec "$@"
 
268
}
 
269
 
 
270
main "$@"
 
271
# vi: ts=4 noexpandtab