5 from importlib
import import_module
6 from importlib
.util
import module_from_spec
, spec_from_file_location
8 from setuptools
import setup
9 from setuptools
.command
.build_py
import build_py
10 from setuptools
.command
.sdist
import sdist
13 # The goal is to get the version without doing a regular/full import of
14 # stgit. Executing the stgit._version module will obtain the version
15 # without importing anything else from the stgit package.
17 spec
= spec_from_file_location('version', os
.path
.join('stgit', '_version.py'))
18 module
= module_from_spec(spec
)
19 spec
.loader
.exec_module(module
)
20 return module
.__version
__
23 version
= _get_version()
26 def _write_version(base_dir
):
27 _version_path
= os
.path
.join(base_dir
, 'stgit', '_version.py')
29 # This could be a hard link, so try to delete it first.
30 os
.remove(_version_path
)
32 os
.makedirs(os
.path
.join(base_dir
, 'stgit'), exist_ok
=True)
33 with
open(_version_path
, "w") as f
:
34 f
.write("# Generated by setup.py.\n\n__version__ = '{}'\n".format(version
))
37 class _stgit_build_py(build_py
):
40 _write_version(self
.build_lib
)
43 class _stgit_sdist(sdist
):
44 def make_release_tree(self
, base_dir
, files
):
45 super().make_release_tree(base_dir
, files
)
46 _write_version(base_dir
)
49 # Override setuptools build_py and sdist commands to rewrite the
50 # _version.py file into those commands' destination trees.
51 # N.B. the _version.py in the worktree is never overwritten.
52 cmdclass
= dict(sdist
=_stgit_sdist
, build_py
=_stgit_build_py
)
55 # Carefully perform code generation. First check if generated code
56 # exists. Only write-out generated code if the content is different.
57 # This accommodates several setup.py contexts, including:
58 # - When running from an sdist where code is already generated
59 # - During pip installation where the stgit package is not in sys.path
60 # - In a git worktree where the generated code may change frequently
61 # - When running from a read-only directory/filesystem
62 def _maybe_generate_code():
63 base
= os
.path
.abspath(os
.path
.dirname(__file__
))
65 cmds
=os
.path
.join(base
, 'stgit', 'commands', 'cmdlist.py'),
66 bash
=os
.path
.join(base
, 'completion', 'stgit.bash'),
67 fish
=os
.path
.join(base
, 'completion', 'stg.fish'),
70 existing_content
= dict()
71 for k
, path
in paths
.items():
72 if os
.path
.exists(path
):
73 with
open(path
, 'r') as f
:
74 existing_content
[k
] = f
.read()
76 existing_content
[k
] = None
78 sys
.path
.insert(0, base
)
82 cmds
=import_module('stgit.commands').write_cmdlist_py
,
83 bash
=import_module('stgit.completion.bash').write_bash_completion
,
84 fish
=import_module('stgit.completion.fish').write_fish_completion
,
87 if all(existing_content
.values()):
88 return # Okay, all generated content exists
90 raise RuntimeError('Cannot perform code generation')
94 for k
, gen_func
in gen_funcs
.items():
95 with io
.StringIO() as f
:
97 new_content
= f
.getvalue()
98 if existing_content
[k
] != new_content
:
99 with
open(paths
[k
], 'w') as f
:
103 _maybe_generate_code()
106 def _long_description():
107 base
= os
.path
.abspath(os
.path
.dirname(__file__
))
109 for fn
in ['README.md', 'CHANGELOG.md']:
110 with
open(os
.path
.join(base
, fn
)) as f
:
111 parts
.append(f
.read())
112 return '\n\n'.join(parts
)
119 author
='Catalin Marinas',
120 author_email
='catalin.marinas@gmail.com',
121 maintainer
='Peter Grayson',
122 maintainer_email
='pete@jpgrayson.net',
123 url
='http://stacked-git.github.io',
124 download_url
='https://github.com/stacked-git/stgit.git',
125 description
='Stacked Git',
126 long_description
=_long_description(),
127 long_description_content_type
='text/markdown',
128 python_requires
='>=3.5',
130 include_package_data
=True,
131 entry_points
=dict(console_scripts
=['stg = stgit.main:main']),
141 'Development Status :: 5 - Production/Stable',
142 'Environment :: Console',
143 'Intended Audience :: Developers',
144 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
145 'Natural Language :: English',
146 'Operating System :: OS Independent',
147 'Programming Language :: Python',
148 'Programming Language :: Python :: 3',
149 'Programming Language :: Python :: 3.5',
150 'Programming Language :: Python :: 3.6',
151 'Programming Language :: Python :: 3.7',
152 'Programming Language :: Python :: 3.8',
153 'Programming Language :: Python :: 3.9',
154 'Programming Language :: Python :: 3.10',
155 'Programming Language :: Python :: Implementation :: CPython',
156 'Programming Language :: Python :: Implementation :: PyPy',
157 'Topic :: Software Development :: Version Control',