From 4cc1dc405f31d3db36a20e6db0816f155d0c9144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 22 Jun 2014 01:06:39 +0200 Subject: [PATCH 01/24] v1.1.0-rc1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 336c3677..8376431e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0-dev +1.1.0-rc1 From f693f26ffc0d6b92394e8f58d34cb33ebef54f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sat, 21 Jun 2014 20:16:53 +0200 Subject: [PATCH 02/24] Insert src folder at first position of sys.path (cherry picked from commit fa564c6) --- run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run b/run index 35ebbef8..0c51da39 100755 --- a/run +++ b/run @@ -16,7 +16,7 @@ I don't know anything about). """ os.rename(old, os.path.join(basedir, "octoprint.backup")) -sys.path.append(os.path.join(basedir, "src")) +sys.path.insert(0, os.path.join(basedir, "src")) import octoprint octoprint.main() From 18162cf11051febc9a1770befc2b052d9468c252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 22 Jun 2014 00:41:03 +0200 Subject: [PATCH 03/24] Versioning by versioneer: https://github.com/warner/python-versioneer/ (cherry picked from commit 285f464) --- .gitattributes | 1 + MANIFEST.in | 2 + setup.py | 10 + src/octoprint/__init__.py | 15 +- src/octoprint/_version.py | 188 ++++++ src/octoprint/server/__init__.py | 16 +- src/octoprint/templates/index.jinja2 | 8 +- versioneer.py | 899 +++++++++++++++++++++++++++ 8 files changed, 1124 insertions(+), 15 deletions(-) create mode 100644 .gitattributes create mode 100644 src/octoprint/_version.py create mode 100644 versioneer.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6e546346 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/octoprint/_version.py export-subst diff --git a/MANIFEST.in b/MANIFEST.in index d47da275..8373cd4d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,4 @@ recursive-include src/octoprint/static * recursive-include src/octoprint/templates * +include versioneer.py +include src/octoprint/_version.py diff --git a/setup.py b/setup.py index 5c407bc0..1dc91f38 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,13 @@ # coding=utf-8 #!/usr/bin/env python +import versioneer +versioneer.VCS = 'git' +versioneer.versionfile_source = 'src/octoprint/_version.py' +versioneer.versionfile_build = 'octoprint/_version.py' +versioneer.tag_prefix = '' +versioneer.parentdir_prefix = 'octoprint-' + from setuptools import setup, find_packages VERSION = open("VERSION").read().strip() @@ -51,6 +58,9 @@ def params(): # "scripts/octoprint.init": "/etc/init.d/octoprint" #} + version = versioneer.get_version() + cmdclass = versioneer.get_cmdclass() + return locals() setup(**params()) diff --git a/src/octoprint/__init__.py b/src/octoprint/__init__.py index dbd06e7d..1258ed84 100644 --- a/src/octoprint/__init__.py +++ b/src/octoprint/__init__.py @@ -3,6 +3,13 @@ import sys from octoprint.daemon import Daemon from octoprint.server import Server +#~~ version + +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions + +#~~ main class class Main(Daemon): def __init__(self, pidfile, configfile, basedir, host, port, debug, allowRoot): @@ -24,6 +31,9 @@ def main(): parser = argparse.ArgumentParser(prog="run") + parser.add_argument("-v", "--version", action="store_true", dest="version", + help="Output OctoPrint's version and exit") + parser.add_argument("-d", "--debug", action="store_true", dest="debug", help="Enable debug mode") @@ -47,6 +57,10 @@ def main(): args = parser.parse_args() + if args.version: + print "OctoPrint version %s" % __version__ + sys.exit(0) + if args.daemon: if sys.platform == "darwin" or sys.platform == "win32": print >> sys.stderr, "Sorry, daemon mode is only supported under Linux right now" @@ -65,4 +79,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/octoprint/_version.py b/src/octoprint/_version.py new file mode 100644 index 00000000..f9a41364 --- /dev/null +++ b/src/octoprint/_version.py @@ -0,0 +1,188 @@ + +# 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.10 (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 +import errno + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False): + assert isinstance(commands, list) + p = None + for c in commands: + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + 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_abs): + # 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: + f = open(versionfile_abs,"r") + for line in f.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) + f.close() + 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(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %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". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs-tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # 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, root, verbose=False): + # this runs 'git' from the root of 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. + + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + stdout = run_command(GITS, ["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(GITS, ["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, root, verbose=False): + # 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 = "octoprint-" +versionfile_source = "src/octoprint/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded variables. + + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if ver: + return ver + + try: + root = os.path.abspath(__file__) + # 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__. + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + except NameError: + return default + + return (versions_from_vcs(tag_prefix, root, verbose) + or versions_from_parentdir(parentdir_prefix, root, verbose) + or default) + diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index 51bf09f9..28f186cc 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -38,17 +38,14 @@ import octoprint.util as util import octoprint.users as users import octoprint.events as events import octoprint.timelapse +import octoprint._version + + +VERSION = octoprint._version.get_versions()['version'] @app.route("/") def index(): - branch = None - commit = None - try: - branch, commit = util.getGitInfo() - except: - pass - return render_template( "index.jinja2", webcamStream=settings().get(["webcam", "stream"]), @@ -60,8 +57,7 @@ def index(): enableSdSupport=settings().get(["feature", "sdSupport"]), firstRun=settings().getBoolean(["server", "firstRun"]) and (userManager is None or not userManager.hasBeenCustomized()), debug=debug, - gitBranch=branch, - gitCommit=commit, + version=VERSION, stylesheet=settings().get(["devel", "stylesheet"]), gcodeMobileThreshold=settings().get(["gcodeViewer", "mobileSizeThreshold"]), gcodeThreshold=settings().get(["gcodeViewer", "sizeThreshold"]) @@ -130,6 +126,8 @@ class Server(): self._initLogging(self._debug) logger = logging.getLogger(__name__) + logger.info("Starting OctoPrint (%s)" % VERSION) + eventManager = events.eventManager() gcodeManager = gcodefiles.GcodeManager() printer = Printer(gcodeManager) diff --git a/src/octoprint/templates/index.jinja2 b/src/octoprint/templates/index.jinja2 index cf323a0b..fa5ebe7b 100644 --- a/src/octoprint/templates/index.jinja2 +++ b/src/octoprint/templates/index.jinja2 @@ -596,11 +596,9 @@