diff options
author | kali <kali@leap.se> | 2012-09-13 04:59:08 +0900 |
---|---|---|
committer | kali <kali@leap.se> | 2012-09-13 04:59:08 +0900 |
commit | 157dbbd6dba18a0b10ba045eab9b1cfca8d579c6 (patch) | |
tree | 06fcac9f0c4d059899e0842c4226720ea3f5106b /src/leap | |
parent | 99058b9f6536a3717ab82a9d77b09d5489334eb5 (diff) | |
parent | ffa95a22b2073f75d51af32232e150bf36395f31 (diff) |
Merge branch 'feature/client-versioning' into develop
Close #533. Using versioneer for fetching version from git info and tags
in a setup friendly way. Added info to logs and small about dialog.
Diffstat (limited to 'src/leap')
-rw-r--r-- | src/leap/__init__.py | 25 | ||||
-rw-r--r-- | src/leap/_version.py | 197 | ||||
-rw-r--r-- | src/leap/app.py | 2 | ||||
-rw-r--r-- | src/leap/baseapp/systray.py | 14 | ||||
-rw-r--r-- | src/leap/baseapp/unitychecks.py | 2 |
5 files changed, 238 insertions, 2 deletions
diff --git a/src/leap/__init__.py b/src/leap/__init__.py index a7ae10e3..75bddd6d 100644 --- a/src/leap/__init__.py +++ b/src/leap/__init__.py @@ -1,5 +1,30 @@ +""" +LEAP Encryption Access Project +website: U{https://leap.se/} +""" + from leap import eip from leap import baseapp from leap import util __all__ = [eip, baseapp, util] + +__version__ = "unknown" +try: + from ._version import get_versions + __version__ = get_versions()['version'] + del get_versions +except ImportError: + #running on a tree that has not run + #the setup.py setver + pass + +__appname__ = "unknown" +try: + from leap._appname import __appname__ +except ImportError: + #running on a tree that has not run + #the setup.py setver + pass + +__full_version__ = __appname__ + '/' + str(__version__) diff --git a/src/leap/_version.py b/src/leap/_version.py new file mode 100644 index 00000000..c33430ea --- /dev/null +++ b/src/leap/_version.py @@ -0,0 +1,197 @@ + +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "$Format:%d$" +git_full = "$Format:%H$" + + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + GIT = "git" + if sys.platform == "win32": + GIT = "git.cmd" + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "" +parentdir_prefix = "leap_client-" +versionfile_source = "src/leap/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver + diff --git a/src/leap/app.py b/src/leap/app.py index 322118c5..b721468f 100644 --- a/src/leap/app.py +++ b/src/leap/app.py @@ -5,6 +5,7 @@ import sip sip.setapi('QVariant', 2) from PyQt4.QtGui import (QApplication, QSystemTrayIcon, QMessageBox) +from leap import __version__ as VERSION from leap.baseapp.mainwindow import LeapWindow from leap.baseapp import unitychecks @@ -45,6 +46,7 @@ def main(): logger.debug('args: %s' % opts) logger.info('Starting app') + logger.info('Running client version %s', VERSION) app = QApplication(sys.argv) unitychecks.do_check() diff --git a/src/leap/baseapp/systray.py b/src/leap/baseapp/systray.py index c696ee74..762dac13 100644 --- a/src/leap/baseapp/systray.py +++ b/src/leap/baseapp/systray.py @@ -1,6 +1,7 @@ from PyQt4 import QtCore from PyQt4 import QtGui +from leap import __version__ as VERSION from leap.gui import mainwindow_rc @@ -82,6 +83,9 @@ class StatusAwareTrayIconMixin(object): self.trayIconMenu.addAction(self.maximizeAction) self.trayIconMenu.addAction(self.restoreAction) self.trayIconMenu.addSeparator() + self.trayIconMenu.addAction(self.aboutAct) + self.trayIconMenu.addAction(self.aboutQtAct) + self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.quitAction) self.trayIcon = QtGui.QSystemTrayIcon(self) @@ -104,9 +108,19 @@ class StatusAwareTrayIconMixin(object): triggered=self.showMaximized) self.restoreAction = QtGui.QAction("&Restore", self, triggered=self.showNormal) + self.aboutAct = QtGui.QAction("&About", self, + triggered=self.about) + self.aboutQtAct = QtGui.QAction("About Q&t", self, + triggered=QtGui.qApp.aboutQt) self.quitAction = QtGui.QAction("&Quit", self, triggered=self.cleanupAndQuit) + def about(self): + # move to widget + QtGui.QMessageBox.about(self, "About", + "Running LEAP client<br>" + "version <b>%s</b>" % VERSION) + def setConnWidget(self, icon_name): oldlayout = self.statusIconBox.layout() diff --git a/src/leap/baseapp/unitychecks.py b/src/leap/baseapp/unitychecks.py index 72c9ee6f..2d06f629 100644 --- a/src/leap/baseapp/unitychecks.py +++ b/src/leap/baseapp/unitychecks.py @@ -10,9 +10,7 @@ import platform import sys from subprocess import Popen, PIPE -logging.basicConfig() logger = logging.getLogger(__name__) -logger.setLevel('DEBUG') from leap.base.constants import APP_NAME from leap.baseapp.dialogs import ErrorDialog |