1+ from __future__ import print_function
2+ import argparse
3+ import logging
4+ import os
5+ import subprocess
6+
7+ """
8+ Define a precise package version that includes any git digests for any commits
9+ made subsequently to a package release.
10+
11+ Example:
12+ 1) Some commits have been made subsequent to an official release (possibly on
13+ a branch), plus some uncommitted modifications. The version would be:
14+ v1.0.4+{gitsha}+localmod
15+ 2) Same scenario, but no uncommitted modifications: v1.0.4+{gitsha}
16+ 3) No commits since the last official release: v1.0.4
17+
18+ These functions are encoded into a separate file from setup.py to support
19+ including precise versions in docker tags.
20+ """
21+
22+ def get_git_version ():
23+ """
24+ Try to get git version like '{tag}+{gitsha}', with the added suffix
25+ "+localmod" if the git repo has had any uncommitted modifications.
26+ The "+{gitsha}" suffix will be dropped if this is the tagged version.
27+ Code adapted from setuptools_git_version which has an MIT license.
28+ https://pypi.org/project/setuptools-git-version/
29+ Note: Only look for tags that start with "2." to avoid tags like "demo-v1.0.1".
30+ """
31+ git_command = "git describe --tags --long --match '2.*' --dirty --always"
32+ fmt = '{tag}+{gitsha}{dirty}'
33+
34+ git_version = subprocess .check_output (git_command , shell = True ).decode ('utf-8' ).strip ()
35+ parts = git_version .split ('-' )
36+ # FYI, if it can't find a tag for whatever reason, len may be 1 or 2
37+ assert len (parts ) in (3 , 4 ), (
38+ "Trouble parsing git version output. Got {}, expected 3 or 4 things "
39+ "separated by dashes. This has been caused by the repository having no "
40+ "available tags, which was solved by fetching from the main repo:\n "
41+ "`git remote add main https://github.com/switch-model/switch.git && "
42+ "git fetch --all`" .format (git_version )
43+ )
44+ if len (parts ) == 4 :
45+ dirty = '+localmod'
46+ else :
47+ dirty = ''
48+ tag , count , sha = parts [:3 ]
49+ if count == '0' and not dirty :
50+ return tag
51+ return fmt .format (tag = tag , gitsha = sha .lstrip ('g' ), dirty = dirty )
52+
53+ def get_and_record_version (repo_path ):
54+ """
55+ Attempt to get an absolute version number that includes commits made since
56+ the last release. If that succeeds, record the absolute version and use it
57+ for the pip catalog. If that fails, fall back to something reasonable and
58+ vague for the pip catalog, using the data from base_version.py.
59+ """
60+ pkg_dir = os .path .join (repo_path , 'switch_model' )
61+ data_dir = os .path .join (pkg_dir , 'data' )
62+ __version__ = None
63+ try :
64+ __version__ = get_git_version ()
65+ with open (os .path .join (data_dir , 'installed_version.txt' ), 'w+' ) as f :
66+ f .write (__version__ )
67+ except subprocess .CalledProcessError as e :
68+ logging .warning (
69+ "Could not call git as a subprocess to determine precise version."
70+ "Falling back to using the static version from version.py" )
71+ logging .exception (e )
72+ except AssertionError as e :
73+ logging .warning ("Trouble parsing git output." )
74+ logging .exception (e )
75+ except Exception as e :
76+ logging .warning (
77+ "Trouble getting precise version from git repository; "
78+ "using base version from switch_model/version.py. "
79+ "Error was: {}" .format (e )
80+ )
81+ if __version__ is None :
82+ module_dat = {}
83+ with open (os .path .join (pkg_dir , 'version.py' )) as fp :
84+ exec (fp .read (), module_dat )
85+ __version__ = module_dat ['__version__' ]
86+ return __version__
87+
88+ def get_args ():
89+ parser = argparse .ArgumentParser (
90+ description = 'Get a precise local version of this git repository' ,
91+ formatter_class = argparse .ArgumentDefaultsHelpFormatter )
92+ parser .add_argument (
93+ '--verbose' , '-v' , dest = 'verbose' , default = False ,
94+ action = 'store_const' , const = logging .WARNING ,
95+ help = 'Show information about model preparation and solution' )
96+ parser .add_argument (
97+ '--very-verbose' , '-vv' , dest = 'verbose' , default = False ,
98+ action = 'store_const' , const = logging .INFO ,
99+ help = 'Show more information about model preparation and solution' )
100+ parser .add_argument (
101+ '--very-very-verbose' , '-vvv' , dest = 'verbose' , default = False ,
102+ action = 'store_const' , const = logging .DEBUG ,
103+ help = 'Show debugging-level information about model preparation and solution' )
104+ parser .add_argument (
105+ '--quiet' , '-q' , dest = 'verbose' , action = 'store_false' ,
106+ help = "Don't show information about model preparation and solution "
107+ "(cancels --verbose setting)" )
108+
109+ args = parser .parse_args ()
110+ return args
111+
112+ def main ():
113+ args = get_args ()
114+ if args .verbose :
115+ logging .basicConfig (format = '%(levelname)s:%(message)s' , level = args .verbose )
116+ repo_path = os .path .dirname (os .path .realpath (__file__ ))
117+ __version__ = get_and_record_version (repo_path )
118+ print (__version__ )
119+
120+ if __name__ == "__main__" :
121+ main ()
0 commit comments