From ff7f3c65f9dfa44e365c84000b6d8a9ba17f1a96 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 3 Nov 2014 01:42:17 -0500 Subject: [PATCH] add vcs version checker --- nvchecker/get_version.py | 2 +- nvchecker/source/vcs.py | 50 ++++++++++++++++++ nvchecker/source/vcs.sh | 106 +++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 nvchecker/source/vcs.py create mode 100644 nvchecker/source/vcs.sh diff --git a/nvchecker/get_version.py b/nvchecker/get_version.py index 93e0fb8..6bedf54 100644 --- a/nvchecker/get_version.py +++ b/nvchecker/get_version.py @@ -4,7 +4,7 @@ from importlib import import_module logger = logging.getLogger(__name__) handler_precedence = ( 'github', 'aur', 'pypi', 'archpkg', 'gems', 'pacman', - 'cmd', 'gcode_hg', 'regex', 'manual', + 'cmd', 'gcode_hg', 'regex', 'manual', 'vcs' ) def get_version(name, conf, callback): diff --git a/nvchecker/source/vcs.py b/nvchecker/source/vcs.py new file mode 100644 index 0000000..e968237 --- /dev/null +++ b/nvchecker/source/vcs.py @@ -0,0 +1,50 @@ +import logging +from functools import partial + +import tornado.process +from tornado.ioloop import IOLoop + +import os.path as _path + +logger = logging.getLogger(__name__) +_self_path = _path.dirname(_path.abspath(__file__)) +_cmd_prefix=['/bin/bash', _path.join(_self_path, 'vcs.sh')] + +PROT_VER = 1 + +def _parse_oldver(oldver): + if oldver is None: + return (PROT_VER, 0, '') + try: + prot_ver, count, ver = oldver.split('.', maxsplit=2) + prot_ver = int(prot_ver) + count = int(count) + except: + return (PROT_VER, 0, '') + if prot_ver != PROT_VER: + return (PROT_VER, 0, ver) + return (PROT_VER, count, ver) + +def get_version(name, conf, callback): + vcs = conf['vcs'] + oldver = conf['oldver'] + cmd = _cmd_prefix + [name, vcs] + p = tornado.process.Subprocess(cmd, io_loop=IOLoop.instance(), + stdout=tornado.process.Subprocess.STREAM) + p.set_exit_callback(partial(_command_done, name, oldver, callback, p)) + +def _command_done(name, oldver, callback, process, status): + if status != 0: + logger.error('%s: command exited with %d.', name, status) + callback(name, None) + else: + process.stdout.read_until_close(partial(_got_version_from_cmd, + callback, name, oldver)) + +def _got_version_from_cmd(callback, name, oldver_str, output): + output = output.strip().decode('latin1') + oldver = _parse_oldver(oldver_str) + if output == oldver[2]: + callback(name, None) + else: + callback(name, "%d.%d.%s" % (oldver[0], oldver[1] + 1, output)) diff --git a/nvchecker/source/vcs.sh b/nvchecker/source/vcs.sh new file mode 100644 index 0000000..a807cf1 --- /dev/null +++ b/nvchecker/source/vcs.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +exec 3>&1 +exec >&2 + +dir=$1 +vcs=$2 + +parse_vcs_url() { + local _url=$1 + local _out_var=$2 + # remove folder:: + [[ $_url =~ ^[^/:]*::(.*)$ ]] && _url=${BASH_REMATCH[1]} + [[ $_url =~ ^(bzr|git|hg|svn)([+:])(.*) ]] || return 1 + local _proto=${BASH_REMATCH[1]} + [[ ${BASH_REMATCH[2]} = + ]] && _url=${BASH_REMATCH[3]} + local _real_url=${_url%\#*} + local _frag='' + [[ $_real_url = $_url ]] || _frag=${_url##*\#} + eval "${_out_var}"'=("${_proto}" "${_real_url}" "${_frag}")' +} + +get_vcs() { + local _vcs=$1 + local _out_var=$2 + if [[ -z $_vcs ]]; then + _vcs=$(. PKGBUILD &> /dev/null + for src in "${source[@]}"; do + parse_vcs_url "$src" _ && { + echo "$src" + exit 0 + } + done + exit 1) || return 1 + fi + parse_vcs_url "$_vcs" "$_out_var" +} + +git_get_version() { + local _url=$1 + local _frag=$2 + local _ref='' + if [[ -z $_frag ]]; then + _ref=HEAD + elif [[ $_frag =~ ^commit=(.*)$ ]]; then + echo "${BASH_REMATCH[1]}" + return 0 + elif [[ $_frag =~ ^branch=(.*)$ ]]; then + _ref=refs/heads/${BASH_REMATCH[1]} + elif [[ $_frag =~ ^tag=(.*)$ ]]; then + _ref=refs/tags/${BASH_REMATCH[1]} + else + return 1 + fi + local _res=$(git ls-remote "$_url" "$_ref") + [[ $_res =~ ^([a-fA-F0-9]*)[[:blank:]] ]] || return 1 + echo "${BASH_REMATCH[1]}" +} + +hg_get_version() { + local _url=$1 + local _frag=$2 + local _ref + if [[ -z $_frag ]]; then + _ref=default + elif [[ $_frag =~ ^(revision|tag|branch)=(.*)$ ]]; then + _ref=${BASH_REMATCH[2]} + else + return 1 + fi + hg identify "${_url}#${_ref}" +} + +svn_get_version() { + local _url=$1 + local _frag=$2 + local _extra_arg=() + if [[ -z $_frag ]]; then + true + elif [[ $_frag =~ ^(revision)=(.*)$ ]]; then + _extra_arg=(-r "${BASH_REMATCH[2]}") + else + return 1 + fi + # Get rid of locale + env -i PATH="${PATH}" svn info "${_extra_arg[@]}" "${_url}" | \ + sed -n 's/^Revision:[[:blank:]]*\([0-9]*\)/\1/p' +} + +bzr_get_version() { + local _url=$1 + local _frag=$2 + local _extra_arg=() + if [[ -z $_frag ]]; then + true + elif [[ $_frag =~ ^(revision)=(.*)$ ]]; then + _extra_arg=(-r "${BASH_REMATCH[2]}") + else + return 1 + fi + bzr revno -q "${_extra_arg[@]}" "${_url}" +} + +cd "${dir}" +get_vcs "${vcs}" components || exit 1 +eval "${components[0]}_get_version"' ${components[@]:1}' >&3 diff --git a/setup.py b/setup.py index c228be4..7d8657e 100755 --- a/setup.py +++ b/setup.py @@ -16,6 +16,7 @@ setup( 'nvcmp = nvchecker.tools:cmp', ], }, + package_data={'nvchecker': ['source/vcs.sh']}, author = 'lilydjwg', author_email = 'lilydjwg@gmail.com',