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