diff --git a/.gitignore b/.gitignore index 6d6fa31..0d6c274 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ records/ +*.egg-info/ +__pycache__/ +/build/ +*.pyc +*.pyo diff --git a/README.rst b/README.rst index 6e1cf92..3d5ec42 100644 --- a/README.rst +++ b/README.rst @@ -131,7 +131,7 @@ gems Check Local Pacman Database --------------------------- -This is used when you run ``nvchecker`` on an Arch Linux system and the program always keeps up with a package in your configured repositories for `Pacman `_. +This is used when you run ``nvchecker`` on an Arch Linux system and the program always keeps up with a package in your configured repositories for `Pacman`_. pacman The package name to reference to. @@ -157,6 +157,13 @@ This enables you to manually specify the version (maybe because you want to appr manual The version string. +Version Control System (VCS) (git, hg, svn, bzr) +------------------------------------------------ +Check a VCS repo for new commits. The version returned is currently not related to the version of the software and will increase whenever the referred VCS branch changes. This is mainly for Arch Linux. + +vcs + The url of the remote VCS repo, using the same syntax with a VCS url in PKGBUILD (`Pacman`_'s build script). The first VCS url found in the source array of the PKGBUILD will be used if this is left blank. (Note: for a blank ``vcs`` setting to work correctly, the PKGBUILD has to be in a directory with the name of the software under the path where nvchecker is run. Also, all the commands, if any, needed when sourcing the PKGBUILD need to be installed). + Other ----- More to come. Send me a patch or pull request if you can't wait and have written one yourself :-) @@ -173,3 +180,5 @@ Footnotes ========= .. [v0.3] Note: with nvchecker <= 0.2, there are one more colon each line. You can use ``sed -i 's/://' FILES...`` to remove them. .. [v0.4] This is added in version 0.4, and old command-line options are removed. + +.. _Pacman: https://wiki.archlinux.org/index.php/Pacman 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..75e5e4a --- /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',