blob: c00770fe4ff7312323aa545fbdf82596cab6c43f [file] [log] [blame]
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -04001
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -04002# Version: 0.14
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -04003
4"""
5The Versioneer
6==============
7
8* like a rocketeer, but for versions!
9* https://github.com/warner/python-versioneer
10* Brian Warner
11* License: Public Domain
12* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, and pypy
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -040013* [![Latest Version]
14(https://pypip.in/version/versioneer/badge.svg?style=flat)
15](https://pypi.python.org/pypi/versioneer/)
16* [![Build Status]
17(https://travis-ci.org/warner/python-versioneer.png?branch=master)
18](https://travis-ci.org/warner/python-versioneer)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -040019
20This is a tool for managing a recorded version number in distutils-based
21python projects. The goal is to remove the tedious and error-prone "update
22the embedded version string" step from your release process. Making a new
23release should be as easy as recording a new tag in your version-control
24system, and maybe making new tarballs.
25
26
27## Quick Install
28
29* `pip install versioneer` to somewhere to your $PATH
30* run `versioneer-installer` in your source tree: this installs `versioneer.py`
31* follow the instructions below (also in the `versioneer.py` docstring)
32
33## Version Identifiers
34
35Source trees come from a variety of places:
36
37* a version-control system checkout (mostly used by developers)
38* a nightly tarball, produced by build automation
39* a snapshot tarball, produced by a web-based VCS browser, like github's
40 "tarball from tag" feature
41* a release tarball, produced by "setup.py sdist", distributed through PyPI
42
43Within each source tree, the version identifier (either a string or a number,
44this tool is format-agnostic) can come from a variety of places:
45
46* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows
47 about recent "tags" and an absolute revision-id
48* the name of the directory into which the tarball was unpacked
49* an expanded VCS keyword ($Id$, etc)
50* a `_version.py` created by some earlier build step
51
52For released software, the version identifier is closely related to a VCS
53tag. Some projects use tag names that include more than just the version
54string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool
55needs to strip the tag prefix to extract the version identifier. For
56unreleased software (between tags), the version identifier should provide
57enough information to help developers recreate the same tree, while also
58giving them an idea of roughly how old the tree is (after version 1.2, before
59version 1.3). Many VCS systems can report a description that captures this,
60for example 'git describe --tags --dirty --always' reports things like
61"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
620.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
63uncommitted changes.
64
65The version identifier is used for multiple purposes:
66
67* to allow the module to self-identify its version: `myproject.__version__`
68* to choose a name and prefix for a 'setup.py sdist' tarball
69
70## Theory of Operation
71
72Versioneer works by adding a special `_version.py` file into your source
73tree, where your `__init__.py` can import it. This `_version.py` knows how to
74dynamically ask the VCS tool for version information at import time. However,
75when you use "setup.py build" or "setup.py sdist", `_version.py` in the new
76copy is replaced by a small static file that contains just the generated
77version data.
78
79`_version.py` also contains `$Revision$` markers, and the installation
80process marks `_version.py` to have this marker rewritten with a tag name
81during the "git archive" command. As a result, generated tarballs will
82contain enough information to get the proper version.
83
84
85## Installation
86
87First, decide on values for the following configuration variables:
88
89* `VCS`: the version control system you use. Currently accepts "git".
90
91* `versionfile_source`:
92
93 A project-relative pathname into which the generated version strings should
94 be written. This is usually a `_version.py` next to your project's main
95 `__init__.py` file, so it can be imported at runtime. If your project uses
96 `src/myproject/__init__.py`, this should be `src/myproject/_version.py`.
97 This file should be checked in to your VCS as usual: the copy created below
98 by `setup.py versioneer` will include code that parses expanded VCS
99 keywords in generated tarballs. The 'build' and 'sdist' commands will
100 replace it with a copy that has just the calculated version string.
101
102 This must be set even if your project does not have any modules (and will
103 therefore never import `_version.py`), since "setup.py sdist" -based trees
104 still need somewhere to record the pre-calculated version strings. Anywhere
105 in the source tree should do. If there is a `__init__.py` next to your
106 `_version.py`, the `setup.py versioneer` command (described below) will
107 append some `__version__`-setting assignments, if they aren't already
108 present.
109
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400110* `versionfile_build`:
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400111
112 Like `versionfile_source`, but relative to the build directory instead of
113 the source directory. These will differ when your setup.py uses
114 'package_dir='. If you have `package_dir={'myproject': 'src/myproject'}`,
115 then you will probably have `versionfile_build='myproject/_version.py'` and
116 `versionfile_source='src/myproject/_version.py'`.
117
118 If this is set to None, then `setup.py build` will not attempt to rewrite
119 any `_version.py` in the built tree. If your project does not have any
120 libraries (e.g. if it only builds a script), then you should use
121 `versionfile_build = None` and override `distutils.command.build_scripts`
122 to explicitly insert a copy of `versioneer.get_version()` into your
123 generated script.
124
125* `tag_prefix`:
126
127 a string, like 'PROJECTNAME-', which appears at the start of all VCS tags.
128 If your tags look like 'myproject-1.2.0', then you should use
129 tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this
130 should be an empty string.
131
132* `parentdir_prefix`:
133
134 a string, frequently the same as tag_prefix, which appears at the start of
135 all unpacked tarball filenames. If your tarball unpacks into
136 'myproject-1.2.0', this should be 'myproject-'.
137
138This tool provides one script, named `versioneer-installer`. That script does
139one thing: write a copy of `versioneer.py` into the current directory.
140
141To versioneer-enable your project:
142
143* 1: Run `versioneer-installer` to copy `versioneer.py` into the top of your
144 source tree.
145
146* 2: add the following lines to the top of your `setup.py`, with the
147 configuration values you decided earlier:
148
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400149 ````
150 import versioneer
151 versioneer.VCS = 'git'
152 versioneer.versionfile_source = 'src/myproject/_version.py'
153 versioneer.versionfile_build = 'myproject/_version.py'
154 versioneer.tag_prefix = '' # tags are like 1.2.0
155 versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0'
156 ````
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400157
158* 3: add the following arguments to the setup() call in your setup.py:
159
160 version=versioneer.get_version(),
161 cmdclass=versioneer.get_cmdclass(),
162
163* 4: now run `setup.py versioneer`, which will create `_version.py`, and will
164 modify your `__init__.py` (if one exists next to `_version.py`) to define
165 `__version__` (by calling a function from `_version.py`). It will also
166 modify your `MANIFEST.in` to include both `versioneer.py` and the generated
167 `_version.py` in sdist tarballs.
168
169* 5: commit these changes to your VCS. To make sure you won't forget,
170 `setup.py versioneer` will mark everything it touched for addition.
171
172## Post-Installation Usage
173
174Once established, all uses of your tree from a VCS checkout should get the
175current version string. All generated tarballs should include an embedded
176version string (so users who unpack them will not need a VCS tool installed).
177
178If you distribute your project through PyPI, then the release process should
179boil down to two steps:
180
181* 1: git tag 1.0
182* 2: python setup.py register sdist upload
183
184If you distribute it through github (i.e. users use github to generate
185tarballs with `git archive`), the process is:
186
187* 1: git tag 1.0
188* 2: git push; git push --tags
189
190Currently, all version strings must be based upon a tag. Versioneer will
191report "unknown" until your tree has at least one tag in its history. This
192restriction will be fixed eventually (see issue #12).
193
194## Version-String Flavors
195
196Code which uses Versioneer can learn about its version string at runtime by
197importing `_version` from your main `__init__.py` file and running the
198`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can
199import the top-level `versioneer.py` and run `get_versions()`.
200
201Both functions return a dictionary with different keys for different flavors
202of the version string:
203
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400204* `['version']`: A condensed PEP440-compliant string, equal to the
205 un-prefixed tag name for actual releases, and containing an additional
206 "local version" section with more detail for in-between builds. For Git,
207 this is TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe
208 --tags --dirty --always`. For example "0.11+2.g1076c97.dirty" indicates
209 that the tree is like the "1076c97" commit but has uncommitted changes
210 (".dirty"), and that this commit is two revisions ("+2") beyond the "0.11"
211 tag. For released software (exactly equal to a known tag), the identifier
212 will only contain the stripped tag, e.g. "0.11".
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400213
214* `['full']`: detailed revision identifier. For Git, this is the full SHA1
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400215 commit id, followed by ".dirty" if the tree contains uncommitted changes,
216 e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac.dirty".
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400217
218Some variants are more useful than others. Including `full` in a bug report
219should allow developers to reconstruct the exact code being tested (or
220indicate the presence of local changes that should be shared with the
221developers). `version` is suitable for display in an "about" box or a CLI
222`--version` output: it can be easily compared against release notes and lists
223of bugs fixed in various releases.
224
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400225The `setup.py versioneer` command adds the following text to your
226`__init__.py` to place a basic version in `YOURPROJECT.__version__`:
227
228 from ._version import get_versions
229 __version__ = get_versions()['version']
230 del get_versions
231
232## Updating Versioneer
233
234To upgrade your project to a new release of Versioneer, do the following:
235
236* install the new Versioneer (`pip install -U versioneer` or equivalent)
237* re-run `versioneer-installer` in your source tree to replace your copy of
238 `versioneer.py`
239* edit `setup.py`, if necessary, to include any new configuration settings
240 indicated by the release notes
241* re-run `setup.py versioneer` to replace `SRC/_version.py`
242* commit any changed files
243
244### Upgrading from 0.10 to 0.11
245
246You must add a `versioneer.VCS = "git"` to your `setup.py` before re-running
247`setup.py versioneer`. This will enable the use of additional version-control
248systems (SVN, etc) in the future.
249
250### Upgrading from 0.11 to 0.12
251
252Nothing special.
253
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400254## Upgrading to 0.14
255
2560.14 changes the format of the version string. 0.13 and earlier used
257hyphen-separated strings like "0.11-2-g1076c97-dirty". 0.14 and beyond use a
258plus-separated "local version" section strings, with dot-separated
259components, like "0.11+2.g1076c97". PEP440-strict tools did not like the old
260format, but should be ok with the new one.
261
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400262## Future Directions
263
264This tool is designed to make it easily extended to other version-control
265systems: all VCS-specific components are in separate directories like
266src/git/ . The top-level `versioneer.py` script is assembled from these
267components by running make-versioneer.py . In the future, make-versioneer.py
268will take a VCS name as an argument, and will construct a version of
269`versioneer.py` that is specific to the given VCS. It might also take the
270configuration arguments that are currently provided manually during
271installation by editing setup.py . Alternatively, it might go the other
272direction and include code from all supported VCS systems, reducing the
273number of intermediate scripts.
274
275
276## License
277
278To make Versioneer easier to embed, all its code is hereby released into the
279public domain. The `_version.py` that it creates is also in the public
280domain.
281
282"""
283
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400284import errno
285import os
286import re
287import subprocess
288import sys
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400289from distutils.command.build import build as _build
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400290from distutils.command.sdist import sdist as _sdist
291from distutils.core import Command
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400292
293# these configuration settings will be overridden by setup.py after it
294# imports us
295versionfile_source = None
296versionfile_build = None
297tag_prefix = None
298parentdir_prefix = None
299VCS = None
300
301# these dictionaries contain VCS-specific tools
302LONG_VERSION_PY = {}
303
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400304
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400305def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
306 assert isinstance(commands, list)
307 p = None
308 for c in commands:
309 try:
310 # remember shell=False, so use git.cmd on windows, not just git
311 p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
312 stderr=(subprocess.PIPE if hide_stderr
313 else None))
314 break
315 except EnvironmentError:
316 e = sys.exc_info()[1]
317 if e.errno == errno.ENOENT:
318 continue
319 if verbose:
320 print("unable to run %s" % args[0])
321 print(e)
322 return None
323 else:
324 if verbose:
325 print("unable to find command, tried %s" % (commands,))
326 return None
327 stdout = p.communicate()[0].strip()
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400328 if sys.version_info[0] >= 3:
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400329 stdout = stdout.decode()
330 if p.returncode != 0:
331 if verbose:
332 print("unable to run %s (error)" % args[0])
333 return None
334 return stdout
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400335LONG_VERSION_PY['git'] = '''
336# This file helps to compute a version number in source trees obtained from
337# git-archive tarball (such as those provided by githubs download-from-tag
338# feature). Distribution tarballs (built by setup.py sdist) and build
339# directories (produced by setup.py build) will contain a much shorter file
340# that just contains the computed version number.
341
342# This file is released into the public domain. Generated by
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400343# versioneer-0.14 (https://github.com/warner/python-versioneer)
344
345import errno
346import os
347import re
348import subprocess
349import sys
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400350
351# these strings will be replaced by git during git-archive
352git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
353git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
354
355# these strings are filled in when 'setup.py versioneer' creates _version.py
356tag_prefix = "%(TAG_PREFIX)s"
357parentdir_prefix = "%(PARENTDIR_PREFIX)s"
358versionfile_source = "%(VERSIONFILE_SOURCE)s"
359
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400360
361def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
362 assert isinstance(commands, list)
363 p = None
364 for c in commands:
365 try:
366 # remember shell=False, so use git.cmd on windows, not just git
367 p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
368 stderr=(subprocess.PIPE if hide_stderr
369 else None))
370 break
371 except EnvironmentError:
372 e = sys.exc_info()[1]
373 if e.errno == errno.ENOENT:
374 continue
375 if verbose:
376 print("unable to run %%s" %% args[0])
377 print(e)
378 return None
379 else:
380 if verbose:
381 print("unable to find command, tried %%s" %% (commands,))
382 return None
383 stdout = p.communicate()[0].strip()
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400384 if sys.version_info[0] >= 3:
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400385 stdout = stdout.decode()
386 if p.returncode != 0:
387 if verbose:
388 print("unable to run %%s (error)" %% args[0])
389 return None
390 return stdout
391
392
393def versions_from_parentdir(parentdir_prefix, root, verbose=False):
394 # Source tarballs conventionally unpack into a directory that includes
395 # both the project name and a version string.
396 dirname = os.path.basename(root)
397 if not dirname.startswith(parentdir_prefix):
398 if verbose:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400399 print("guessing rootdir is '%%s', but '%%s' doesn't start with "
400 "prefix '%%s'" %% (root, dirname, parentdir_prefix))
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400401 return None
402 return {"version": dirname[len(parentdir_prefix):], "full": ""}
403
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400404
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400405def git_get_keywords(versionfile_abs):
406 # the code embedded in _version.py can just fetch the value of these
407 # keywords. When used from setup.py, we don't want to import _version.py,
408 # so we do it with a regexp instead. This function is not used from
409 # _version.py.
410 keywords = {}
411 try:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400412 f = open(versionfile_abs, "r")
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400413 for line in f.readlines():
414 if line.strip().startswith("git_refnames ="):
415 mo = re.search(r'=\s*"(.*)"', line)
416 if mo:
417 keywords["refnames"] = mo.group(1)
418 if line.strip().startswith("git_full ="):
419 mo = re.search(r'=\s*"(.*)"', line)
420 if mo:
421 keywords["full"] = mo.group(1)
422 f.close()
423 except EnvironmentError:
424 pass
425 return keywords
426
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400427
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400428def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
429 if not keywords:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400430 return {} # keyword-finding function failed to find keywords
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400431 refnames = keywords["refnames"].strip()
432 if refnames.startswith("$Format"):
433 if verbose:
434 print("keywords are unexpanded, not using")
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400435 return {} # unexpanded, so not in an unpacked git-archive tarball
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400436 refs = set([r.strip() for r in refnames.strip("()").split(",")])
437 # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
438 # just "foo-1.0". If we see a "tag: " prefix, prefer those.
439 TAG = "tag: "
440 tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
441 if not tags:
442 # Either we're using git < 1.8.3, or there really are no tags. We use
443 # a heuristic: assume all version tags have a digit. The old git %%d
444 # expansion behaves like git log --decorate=short and strips out the
445 # refs/heads/ and refs/tags/ prefixes that would let us distinguish
446 # between branches and tags. By ignoring refnames without digits, we
447 # filter out many common branch names like "release" and
448 # "stabilization", as well as "HEAD" and "master".
449 tags = set([r for r in refs if re.search(r'\d', r)])
450 if verbose:
451 print("discarding '%%s', no digits" %% ",".join(refs-tags))
452 if verbose:
453 print("likely tags: %%s" %% ",".join(sorted(tags)))
454 for ref in sorted(tags):
455 # sorting will prefer e.g. "2.0" over "2.0rc1"
456 if ref.startswith(tag_prefix):
457 r = ref[len(tag_prefix):]
458 if verbose:
459 print("picking %%s" %% r)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400460 return {"version": r,
461 "full": keywords["full"].strip()}
462 # no suitable tags, so version is "0+unknown", but full hex is still there
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400463 if verbose:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400464 print("no suitable tags, using unknown + full revision id")
465 return {"version": "0+unknown",
466 "full": keywords["full"].strip()}
467
468
469def git_parse_vcs_describe(git_describe, tag_prefix, verbose=False):
470 # TAG-NUM-gHEX[-dirty] or HEX[-dirty] . TAG might have hyphens.
471
472 # dirty
473 dirty = git_describe.endswith("-dirty")
474 if dirty:
475 git_describe = git_describe[:git_describe.rindex("-dirty")]
476 dirty_suffix = ".dirty" if dirty else ""
477
478 # now we have TAG-NUM-gHEX or HEX
479
480 if "-" not in git_describe: # just HEX
481 return "0+untagged.g"+git_describe+dirty_suffix, dirty
482
483 # just TAG-NUM-gHEX
484 mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
485 if not mo:
486 # unparseable. Maybe git-describe is misbehaving?
487 return "0+unparseable"+dirty_suffix, dirty
488
489 # tag
490 full_tag = mo.group(1)
491 if not full_tag.startswith(tag_prefix):
492 if verbose:
493 fmt = "tag '%%s' doesn't start with prefix '%%s'"
494 print(fmt %% (full_tag, tag_prefix))
495 return None, dirty
496 tag = full_tag[len(tag_prefix):]
497
498 # distance: number of commits since tag
499 distance = int(mo.group(2))
500
501 # commit: short hex revision ID
502 commit = mo.group(3)
503
504 # now build up version string, with post-release "local version
505 # identifier". Our goal: TAG[+NUM.gHEX[.dirty]] . Note that if you get a
506 # tagged build and then dirty it, you'll get TAG+0.gHEX.dirty . So you
507 # can always test version.endswith(".dirty").
508 version = tag
509 if distance or dirty:
510 version += "+%%d.g%%s" %% (distance, commit) + dirty_suffix
511
512 return version, dirty
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400513
514
515def git_versions_from_vcs(tag_prefix, root, verbose=False):
516 # this runs 'git' from the root of the source tree. This only gets called
517 # if the git-archive 'subst' keywords were *not* expanded, and
518 # _version.py hasn't already been rewritten with a short version string,
519 # meaning we're inside a checked out source tree.
520
521 if not os.path.exists(os.path.join(root, ".git")):
522 if verbose:
523 print("no .git in %%s" %% root)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400524 return {} # get_versions() will try next method
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400525
526 GITS = ["git"]
527 if sys.platform == "win32":
528 GITS = ["git.cmd", "git.exe"]
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400529 # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
530 # if there are no tags, this yields HEX[-dirty] (no NUM)
531 stdout = run_command(GITS, ["describe", "--tags", "--dirty",
532 "--always", "--long"],
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400533 cwd=root)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400534 # --long was added in git-1.5.5
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400535 if stdout is None:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400536 return {} # try next method
537 version, dirty = git_parse_vcs_describe(stdout, tag_prefix, verbose)
538
539 # build "full", which is FULLHEX[.dirty]
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400540 stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
541 if stdout is None:
542 return {}
543 full = stdout.strip()
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400544 if dirty:
545 full += ".dirty"
546
547 return {"version": version, "full": full}
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400548
549
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400550def get_versions(default={"version": "0+unknown", "full": ""}, verbose=False):
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400551 # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
552 # __file__, we can work backwards from there to the root. Some
553 # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
554 # case we can only use expanded keywords.
555
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400556 keywords = {"refnames": git_refnames, "full": git_full}
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400557 ver = git_versions_from_keywords(keywords, tag_prefix, verbose)
558 if ver:
559 return ver
560
561 try:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400562 root = os.path.realpath(__file__)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400563 # versionfile_source is the relative path from the top of the source
564 # tree (where the .git directory might live) to this file. Invert
565 # this to find the root from __file__.
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400566 for i in versionfile_source.split('/'):
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400567 root = os.path.dirname(root)
568 except NameError:
569 return default
570
571 return (git_versions_from_vcs(tag_prefix, root, verbose)
572 or versions_from_parentdir(parentdir_prefix, root, verbose)
573 or default)
574'''
575
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400576
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400577def git_get_keywords(versionfile_abs):
578 # the code embedded in _version.py can just fetch the value of these
579 # keywords. When used from setup.py, we don't want to import _version.py,
580 # so we do it with a regexp instead. This function is not used from
581 # _version.py.
582 keywords = {}
583 try:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400584 f = open(versionfile_abs, "r")
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400585 for line in f.readlines():
586 if line.strip().startswith("git_refnames ="):
587 mo = re.search(r'=\s*"(.*)"', line)
588 if mo:
589 keywords["refnames"] = mo.group(1)
590 if line.strip().startswith("git_full ="):
591 mo = re.search(r'=\s*"(.*)"', line)
592 if mo:
593 keywords["full"] = mo.group(1)
594 f.close()
595 except EnvironmentError:
596 pass
597 return keywords
598
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400599
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400600def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
601 if not keywords:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400602 return {} # keyword-finding function failed to find keywords
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400603 refnames = keywords["refnames"].strip()
604 if refnames.startswith("$Format"):
605 if verbose:
606 print("keywords are unexpanded, not using")
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400607 return {} # unexpanded, so not in an unpacked git-archive tarball
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400608 refs = set([r.strip() for r in refnames.strip("()").split(",")])
609 # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
610 # just "foo-1.0". If we see a "tag: " prefix, prefer those.
611 TAG = "tag: "
612 tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
613 if not tags:
614 # Either we're using git < 1.8.3, or there really are no tags. We use
615 # a heuristic: assume all version tags have a digit. The old git %d
616 # expansion behaves like git log --decorate=short and strips out the
617 # refs/heads/ and refs/tags/ prefixes that would let us distinguish
618 # between branches and tags. By ignoring refnames without digits, we
619 # filter out many common branch names like "release" and
620 # "stabilization", as well as "HEAD" and "master".
621 tags = set([r for r in refs if re.search(r'\d', r)])
622 if verbose:
623 print("discarding '%s', no digits" % ",".join(refs-tags))
624 if verbose:
625 print("likely tags: %s" % ",".join(sorted(tags)))
626 for ref in sorted(tags):
627 # sorting will prefer e.g. "2.0" over "2.0rc1"
628 if ref.startswith(tag_prefix):
629 r = ref[len(tag_prefix):]
630 if verbose:
631 print("picking %s" % r)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400632 return {"version": r,
633 "full": keywords["full"].strip()}
634 # no suitable tags, so version is "0+unknown", but full hex is still there
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400635 if verbose:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400636 print("no suitable tags, using unknown + full revision id")
637 return {"version": "0+unknown",
638 "full": keywords["full"].strip()}
639
640
641def git_parse_vcs_describe(git_describe, tag_prefix, verbose=False):
642 # TAG-NUM-gHEX[-dirty] or HEX[-dirty] . TAG might have hyphens.
643
644 # dirty
645 dirty = git_describe.endswith("-dirty")
646 if dirty:
647 git_describe = git_describe[:git_describe.rindex("-dirty")]
648 dirty_suffix = ".dirty" if dirty else ""
649
650 # now we have TAG-NUM-gHEX or HEX
651
652 if "-" not in git_describe: # just HEX
653 return "0+untagged.g"+git_describe+dirty_suffix, dirty
654
655 # just TAG-NUM-gHEX
656 mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
657 if not mo:
658 # unparseable. Maybe git-describe is misbehaving?
659 return "0+unparseable"+dirty_suffix, dirty
660
661 # tag
662 full_tag = mo.group(1)
663 if not full_tag.startswith(tag_prefix):
664 if verbose:
665 fmt = "tag '%s' doesn't start with prefix '%s'"
666 print(fmt % (full_tag, tag_prefix))
667 return None, dirty
668 tag = full_tag[len(tag_prefix):]
669
670 # distance: number of commits since tag
671 distance = int(mo.group(2))
672
673 # commit: short hex revision ID
674 commit = mo.group(3)
675
676 # now build up version string, with post-release "local version
677 # identifier". Our goal: TAG[+NUM.gHEX[.dirty]] . Note that if you get a
678 # tagged build and then dirty it, you'll get TAG+0.gHEX.dirty . So you
679 # can always test version.endswith(".dirty").
680 version = tag
681 if distance or dirty:
682 version += "+%d.g%s" % (distance, commit) + dirty_suffix
683
684 return version, dirty
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400685
686
687def git_versions_from_vcs(tag_prefix, root, verbose=False):
688 # this runs 'git' from the root of the source tree. This only gets called
689 # if the git-archive 'subst' keywords were *not* expanded, and
690 # _version.py hasn't already been rewritten with a short version string,
691 # meaning we're inside a checked out source tree.
692
693 if not os.path.exists(os.path.join(root, ".git")):
694 if verbose:
695 print("no .git in %s" % root)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400696 return {} # get_versions() will try next method
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400697
698 GITS = ["git"]
699 if sys.platform == "win32":
700 GITS = ["git.cmd", "git.exe"]
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400701 # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
702 # if there are no tags, this yields HEX[-dirty] (no NUM)
703 stdout = run_command(GITS, ["describe", "--tags", "--dirty",
704 "--always", "--long"],
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400705 cwd=root)
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400706 # --long was added in git-1.5.5
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400707 if stdout is None:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400708 return {} # try next method
709 version, dirty = git_parse_vcs_describe(stdout, tag_prefix, verbose)
710
711 # build "full", which is FULLHEX[.dirty]
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400712 stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
713 if stdout is None:
714 return {}
715 full = stdout.strip()
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400716 if dirty:
717 full += ".dirty"
718
719 return {"version": version, "full": full}
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400720
721
722def do_vcs_install(manifest_in, versionfile_source, ipy):
723 GITS = ["git"]
724 if sys.platform == "win32":
725 GITS = ["git.cmd", "git.exe"]
726 files = [manifest_in, versionfile_source]
727 if ipy:
728 files.append(ipy)
729 try:
730 me = __file__
731 if me.endswith(".pyc") or me.endswith(".pyo"):
732 me = os.path.splitext(me)[0] + ".py"
733 versioneer_file = os.path.relpath(me)
734 except NameError:
735 versioneer_file = "versioneer.py"
736 files.append(versioneer_file)
737 present = False
738 try:
739 f = open(".gitattributes", "r")
740 for line in f.readlines():
741 if line.strip().startswith(versionfile_source):
742 if "export-subst" in line.strip().split()[1:]:
743 present = True
744 f.close()
745 except EnvironmentError:
746 pass
747 if not present:
748 f = open(".gitattributes", "a+")
749 f.write("%s export-subst\n" % versionfile_source)
750 f.close()
751 files.append(".gitattributes")
752 run_command(GITS, ["add", "--"] + files)
753
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400754
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400755def versions_from_parentdir(parentdir_prefix, root, verbose=False):
756 # Source tarballs conventionally unpack into a directory that includes
757 # both the project name and a version string.
758 dirname = os.path.basename(root)
759 if not dirname.startswith(parentdir_prefix):
760 if verbose:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400761 print("guessing rootdir is '%s', but '%s' doesn't start with "
762 "prefix '%s'" % (root, dirname, parentdir_prefix))
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400763 return None
764 return {"version": dirname[len(parentdir_prefix):], "full": ""}
765
766SHORT_VERSION_PY = """
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400767# This file was generated by 'versioneer.py' (0.14) from
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400768# revision-control system data, or from the parent directory name of an
769# unpacked source archive. Distribution tarballs contain a pre-generated copy
770# of this file.
771
772version_version = '%(version)s'
773version_full = '%(full)s'
774def get_versions(default={}, verbose=False):
775 return {'version': version_version, 'full': version_full}
776
777"""
778
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400779DEFAULT = {"version": "0+unknown", "full": "unknown"}
780
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400781
782def versions_from_file(filename):
783 versions = {}
784 try:
785 with open(filename) as f:
786 for line in f.readlines():
787 mo = re.match("version_version = '([^']+)'", line)
788 if mo:
789 versions["version"] = mo.group(1)
790 mo = re.match("version_full = '([^']+)'", line)
791 if mo:
792 versions["full"] = mo.group(1)
793 except EnvironmentError:
794 return {}
795
796 return versions
797
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400798
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400799def write_to_version_file(filename, versions):
800 with open(filename, "w") as f:
801 f.write(SHORT_VERSION_PY % versions)
802
803 print("set %s to '%s'" % (filename, versions["version"]))
804
805
806def get_root():
807 try:
808 return os.path.dirname(os.path.abspath(__file__))
809 except NameError:
810 return os.path.dirname(os.path.abspath(sys.argv[0]))
811
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400812
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400813def vcs_function(vcs, suffix):
814 return getattr(sys.modules[__name__], '%s_%s' % (vcs, suffix), None)
815
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400816
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400817def get_versions(default=DEFAULT, verbose=False):
818 # returns dict with two keys: 'version' and 'full'
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400819 assert versionfile_source is not None, \
820 "please set versioneer.versionfile_source"
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400821 assert tag_prefix is not None, "please set versioneer.tag_prefix"
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400822 assert parentdir_prefix is not None, \
823 "please set versioneer.parentdir_prefix"
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400824 assert VCS is not None, "please set versioneer.VCS"
825
826 # I am in versioneer.py, which must live at the top of the source tree,
827 # which we use to compute the root directory. py2exe/bbfreeze/non-CPython
828 # don't have __file__, in which case we fall back to sys.argv[0] (which
829 # ought to be the setup.py script). We prefer __file__ since that's more
830 # robust in cases where setup.py was invoked in some weird way (e.g. pip)
831 root = get_root()
832 versionfile_abs = os.path.join(root, versionfile_source)
833
834 # extract version from first of _version.py, VCS command (e.g. 'git
835 # describe'), parentdir. This is meant to work for developers using a
836 # source checkout, for users of a tarball created by 'setup.py sdist',
837 # and for users of a tarball/zipball created by 'git archive' or github's
838 # download-from-tag feature or the equivalent in other VCSes.
839
840 get_keywords_f = vcs_function(VCS, "get_keywords")
841 versions_from_keywords_f = vcs_function(VCS, "versions_from_keywords")
842 if get_keywords_f and versions_from_keywords_f:
843 vcs_keywords = get_keywords_f(versionfile_abs)
844 ver = versions_from_keywords_f(vcs_keywords, tag_prefix)
845 if ver:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400846 if verbose:
847 print("got version from expanded keyword %s" % ver)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400848 return ver
849
850 ver = versions_from_file(versionfile_abs)
851 if ver:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400852 if verbose:
853 print("got version from file %s %s" % (versionfile_abs, ver))
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400854 return ver
855
856 versions_from_vcs_f = vcs_function(VCS, "versions_from_vcs")
857 if versions_from_vcs_f:
858 ver = versions_from_vcs_f(tag_prefix, root, verbose)
859 if ver:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400860 if verbose:
861 print("got version from VCS %s" % ver)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400862 return ver
863
864 ver = versions_from_parentdir(parentdir_prefix, root, verbose)
865 if ver:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400866 if verbose:
867 print("got version from parentdir %s" % ver)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400868 return ver
869
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400870 if verbose:
871 print("got version from default %s" % default)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400872 return default
873
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400874
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400875def get_version(verbose=False):
876 return get_versions(verbose=verbose)["version"]
877
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400878
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400879class cmd_version(Command):
880 description = "report generated version string"
881 user_options = []
882 boolean_options = []
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400883
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400884 def initialize_options(self):
885 pass
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400886
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400887 def finalize_options(self):
888 pass
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400889
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400890 def run(self):
891 ver = get_version(verbose=True)
892 print("Version is currently: %s" % ver)
893
894
895class cmd_build(_build):
896 def run(self):
897 versions = get_versions(verbose=True)
898 _build.run(self)
899 # now locate _version.py in the new build/ directory and replace it
900 # with an updated value
901 if versionfile_build:
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400902 target_versionfile = os.path.join(self.build_lib,
903 versionfile_build)
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400904 print("UPDATING %s" % target_versionfile)
905 os.unlink(target_versionfile)
906 with open(target_versionfile, "w") as f:
907 f.write(SHORT_VERSION_PY % versions)
908
909if 'cx_Freeze' in sys.modules: # cx_freeze enabled?
910 from cx_Freeze.dist import build_exe as _build_exe
911
912 class cmd_build_exe(_build_exe):
913 def run(self):
914 versions = get_versions(verbose=True)
915 target_versionfile = versionfile_source
916 print("UPDATING %s" % target_versionfile)
917 os.unlink(target_versionfile)
918 with open(target_versionfile, "w") as f:
919 f.write(SHORT_VERSION_PY % versions)
920
921 _build_exe.run(self)
922 os.unlink(target_versionfile)
923 with open(versionfile_source, "w") as f:
924 assert VCS is not None, "please set versioneer.VCS"
925 LONG = LONG_VERSION_PY[VCS]
926 f.write(LONG % {"DOLLAR": "$",
927 "TAG_PREFIX": tag_prefix,
928 "PARENTDIR_PREFIX": parentdir_prefix,
929 "VERSIONFILE_SOURCE": versionfile_source,
930 })
931
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400932
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400933class cmd_sdist(_sdist):
934 def run(self):
935 versions = get_versions(verbose=True)
936 self._versioneer_generated_versions = versions
937 # unless we update this, the command will keep using the old version
938 self.distribution.metadata.version = versions["version"]
939 return _sdist.run(self)
940
941 def make_release_tree(self, base_dir, files):
942 _sdist.make_release_tree(self, base_dir, files)
943 # now locate _version.py in the new base_dir directory (remembering
944 # that it may be a hardlink) and replace it with an updated value
945 target_versionfile = os.path.join(base_dir, versionfile_source)
946 print("UPDATING %s" % target_versionfile)
947 os.unlink(target_versionfile)
948 with open(target_versionfile, "w") as f:
949 f.write(SHORT_VERSION_PY % self._versioneer_generated_versions)
950
951INIT_PY_SNIPPET = """
952from ._version import get_versions
953__version__ = get_versions()['version']
954del get_versions
955"""
956
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400957
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400958class cmd_update_files(Command):
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400959 description = ("install/upgrade Versioneer files: "
960 "__init__.py SRC/_version.py")
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400961 user_options = []
962 boolean_options = []
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400963
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400964 def initialize_options(self):
965 pass
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400966
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400967 def finalize_options(self):
968 pass
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -0400969
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -0400970 def run(self):
971 print(" creating %s" % versionfile_source)
972 with open(versionfile_source, "w") as f:
973 assert VCS is not None, "please set versioneer.VCS"
974 LONG = LONG_VERSION_PY[VCS]
975 f.write(LONG % {"DOLLAR": "$",
976 "TAG_PREFIX": tag_prefix,
977 "PARENTDIR_PREFIX": parentdir_prefix,
978 "VERSIONFILE_SOURCE": versionfile_source,
979 })
980
981 ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py")
982 if os.path.exists(ipy):
983 try:
984 with open(ipy, "r") as f:
985 old = f.read()
986 except EnvironmentError:
987 old = ""
988 if INIT_PY_SNIPPET not in old:
989 print(" appending to %s" % ipy)
990 with open(ipy, "a") as f:
991 f.write(INIT_PY_SNIPPET)
992 else:
993 print(" %s unmodified" % ipy)
994 else:
995 print(" %s doesn't exist, ok" % ipy)
996 ipy = None
997
998 # Make sure both the top-level "versioneer.py" and versionfile_source
999 # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so
1000 # they'll be copied into source distributions. Pip won't be able to
1001 # install the package without this.
1002 manifest_in = os.path.join(get_root(), "MANIFEST.in")
1003 simple_includes = set()
1004 try:
1005 with open(manifest_in, "r") as f:
1006 for line in f:
1007 if line.startswith("include "):
1008 for include in line.split()[1:]:
1009 simple_includes.add(include)
1010 except EnvironmentError:
1011 pass
1012 # That doesn't cover everything MANIFEST.in can do
1013 # (http://docs.python.org/2/distutils/sourcedist.html#commands), so
1014 # it might give some false negatives. Appending redundant 'include'
1015 # lines is safe, though.
1016 if "versioneer.py" not in simple_includes:
1017 print(" appending 'versioneer.py' to MANIFEST.in")
1018 with open(manifest_in, "a") as f:
1019 f.write("include versioneer.py\n")
1020 else:
1021 print(" 'versioneer.py' already in MANIFEST.in")
1022 if versionfile_source not in simple_includes:
1023 print(" appending versionfile_source ('%s') to MANIFEST.in" %
1024 versionfile_source)
1025 with open(manifest_in, "a") as f:
1026 f.write("include %s\n" % versionfile_source)
1027 else:
1028 print(" versionfile_source already in MANIFEST.in")
1029
1030 # Make VCS-specific changes. For git, this means creating/changing
1031 # .gitattributes to mark _version.py for export-time keyword
1032 # substitution.
1033 do_vcs_install(manifest_in, versionfile_source, ipy)
1034
Itamar Turner-Trauring6bb399b2015-04-28 09:46:10 -04001035
Itamar Turner-Trauringf60e9a02014-10-18 10:10:46 -04001036def get_cmdclass():
1037 cmds = {'version': cmd_version,
1038 'versioneer': cmd_update_files,
1039 'build': cmd_build,
1040 'sdist': cmd_sdist,
1041 }
1042 if 'cx_Freeze' in sys.modules: # cx_freeze enabled?
1043 cmds['build_exe'] = cmd_build_exe
1044 del cmds['build']
1045
1046 return cmds