diff options
-rw-r--r-- | doc/source/index.rst | 8 | ||||
-rw-r--r-- | doc/source/packagers.rst | 59 | ||||
-rw-r--r-- | pbr/packaging.py | 51 | ||||
-rw-r--r-- | pbr/testr_command.py | 9 | ||||
-rw-r--r-- | pbr/tests/test_setup.py | 2 | ||||
-rw-r--r-- | tools/integration.sh | 9 | ||||
-rw-r--r-- | tox.ini | 1 |
7 files changed, 110 insertions, 29 deletions
diff --git a/doc/source/index.rst b/doc/source/index.rst index d3761d7..d05657b 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -191,6 +191,14 @@ installed for `pbr.config.drivers`, one called `plain` which maps to the `Plain` class in `pbr.cfg.driver` and one called `fancy` which maps to the `Fancy` class in `pbr.cfg.driver`. +Packager Notes +============== + +.. toctree:: + :maxdepth: 1 + + packagers + Indices and tables ================== diff --git a/doc/source/packagers.rst b/doc/source/packagers.rst new file mode 100644 index 0000000..b1ee358 --- /dev/null +++ b/doc/source/packagers.rst @@ -0,0 +1,59 @@ +===================== + Notes for Packagers +===================== + +If you are maintaining packages of software that uses `pbr`, there are some +features you probably want to be aware of that can make your life easier. +They are exposed by environment variables, so adding them to rules or spec +files should be fairly easy. + +Versioning +========== + +`pbr`, when run in a git repo, derives the version of a package from the +git tags. When run in a tarball with a proper egg-info dir, it will happily +pull the version from that. So for the most part, the packager shouldn't need +to care. However, if you are doing something like keeping a git repo with +the sources and the packaging intermixed and it's causing pbr to get confused +about whether its in its own git repo or not, you can set `PBR_VERSION`: + +:: + + PBR_VERSION=1.2.3 + +and all version calculation logic will be completely skipped and the supplied +version will be considered absolute. + +Dependencies +============ + +`pbr` overrides almost everything having to do with python dependency +resolution and calls out to `pip`. In the python source package world this +leads to a more consistent experience. However, in the distro packaging world, +dependencies are handled by the distro. Setting `SKIP_PIP_INSTALL`: + +:: + + SKIP_PIP_INSTALL=1 + +will cause all logic around use of `pip` to be skipped, including the logic +that includes pip as a dependency of `pbr` itself. + +Tarballs +======== + +`pbr` includes everything in a source tarball that is in the original `git` +repository. This can again cause havoc if a packager is doing fancy things +with combined `git` repos, and is generating a source tarball using `python +setup.py sdist` from that repo. If that is the workflow the packager is using, +setting `SKIP_GIT_SDIST`: + +:: + + SKIP_GIT_SDIST=1 + +will cause all logic around using git to find the files that should be in the +source tarball to be skipped. Beware though, that because `pbr` packages +automatically find all of the files, most of them do not have a complete +`MANIFEST.in` file, so its possible that a tarball produced in that way will +be missing files. diff --git a/pbr/packaging.py b/pbr/packaging.py index a97880c..dbbfe0a 100644 --- a/pbr/packaging.py +++ b/pbr/packaging.py @@ -23,6 +23,7 @@ Utilities with minimum-depends for use in setup.py import email import os import re +import shlex import subprocess import sys @@ -95,9 +96,9 @@ def _pip_install(links, requires, root=None, option_dict=dict()): return root_cmd = "" if root: - root_cmd = "--root=%s" % root + root_cmd = "--root=\"%s\"" % root _run_shell_command( - "%s -m pip.__init__ install %s %s %s" % ( + "\"%s\" -m pip.__init__ install %s %s %s" % ( sys.executable, root_cmd, " ".join(links), @@ -210,14 +211,13 @@ def _run_shell_command(cmd, throw_on_error=False, buffer=True): out_location = None err_location = None - if os.name == 'nt': - output = subprocess.Popen(["cmd.exe", "/C", cmd], - stdout=out_location, - stderr=err_location) - else: - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=out_location, - stderr=err_location) + # shlex has issues with unicode on older versions + if sys.version_info < (2, 7): + cmd = cmd.encode('ascii') + + output = subprocess.Popen(shlex.split(cmd), + stdout=out_location, + stderr=err_location) out = output.communicate() if output.returncode and throw_on_error: raise distutils.errors.DistutilsError( @@ -252,7 +252,7 @@ def write_git_changelog(git_dir=None, dest_dir=os.path.curdir, if git_dir is None: git_dir = _get_git_directory() if git_dir: - git_log_cmd = 'git --git-dir=%s log' % git_dir + git_log_cmd = 'git --git-dir=\"%s\" log' % git_dir changelog = _run_shell_command(git_log_cmd) mailmap = read_git_mailmap() with open(new_changelog, "wb") as changelog_file: @@ -279,18 +279,18 @@ def generate_authors(git_dir=None, dest_dir='.', option_dict=dict()): authors = [] # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>'" - " | egrep -v '" + ignore_emails + "'") + git_log_cmd = ("git --git-dir=\"" + git_dir + + "\" log --format='%aN <%aE>'") authors += _run_shell_command(git_log_cmd).split('\n') + authors = [a for a in authors if not re.search(ignore_emails, a)] # get all co-authors from commit messages - co_authors_cmd = ("git log --git-dir=" + git_dir + - " | grep -i Co-authored-by:") - co_authors = _run_shell_command(co_authors_cmd) - + co_authors_cmd = ("git log --git-dir=\"" + git_dir + "\"") + co_authors_out = _run_shell_command(co_authors_cmd) + co_authors = re.findall('Co-authored-by:.+', co_authors_out, + re.MULTILINE) co_authors = [signed.split(":", 1)[1].strip() - for signed in co_authors.split('\n') if signed] + for signed in co_authors if signed] authors += co_authors @@ -319,7 +319,7 @@ def _find_git_files(dirname='', git_dir=None): git_dir = _get_git_directory() if git_dir: log.info("[pbr] In git context, generating filelist from git") - git_ls_cmd = "git --git-dir=%s ls-files -z" % git_dir + git_ls_cmd = "git --git-dir=\"%s\" ls-files -z" % git_dir file_list = _run_shell_command(git_ls_cmd) file_list = file_list.split(b'\x00'.decode('utf-8')) return [f for f in file_list if f] @@ -743,13 +743,13 @@ def _get_revno(git_dir): of time. """ describe = _run_shell_command( - "git --git-dir=%s describe --always" % git_dir) + "git --git-dir=\"%s\" describe --always" % git_dir) if "-" in describe: return describe.rsplit("-", 2)[-2] # no tags found revlist = _run_shell_command( - "git --git-dir=%s rev-list --abbrev-commit HEAD" % git_dir) + "git --git-dir=\"%s\" rev-list --abbrev-commit HEAD" % git_dir) return len(revlist.splitlines()) @@ -764,15 +764,16 @@ def _get_version_from_git(pre_version): if pre_version: try: return _run_shell_command( - "git --git-dir=" + git_dir + " describe --exact-match", + "git --git-dir=\"" + git_dir + "\" describe --exact-match", throw_on_error=True).replace('-', '.') except Exception: sha = _run_shell_command( - "git --git-dir=" + git_dir + " log -n1 --pretty=format:%h") + "git --git-dir=\"" + git_dir + + "\" log -n1 --pretty=format:%h") return "%s.a%s.g%s" % (pre_version, _get_revno(git_dir), sha) else: return _run_shell_command( - "git --git-dir=" + git_dir + " describe --always").replace( + "git --git-dir=\"" + git_dir + "\" describe --always").replace( '-', '.') return None diff --git a/pbr/testr_command.py b/pbr/testr_command.py index 23699dc..cf2a075 100644 --- a/pbr/testr_command.py +++ b/pbr/testr_command.py @@ -56,9 +56,10 @@ class Testr(cmd.Command): ('testr-args=', 't', "Run 'testr' with these args"), ('omit=', 'o', 'Files to omit from coverage calculations'), ('slowest', None, "Show slowest test times after tests complete."), + ('no-parallel', None, "Run testr serially"), ] - boolean_options = ['coverage', 'slowest'] + boolean_options = ['coverage', 'slowest', 'no_parallel'] def _run_testr(self, *args): return commands.run_argv([sys.argv[0]] + list(args), @@ -69,6 +70,7 @@ class Testr(cmd.Command): self.coverage = None self.omit = "" self.slowest = None + self.no_parallel = None def finalize_options(self): if self.testr_args is None: @@ -85,7 +87,10 @@ class Testr(cmd.Command): if self.coverage: self._coverage_before() - testr_ret = self._run_testr("run", "--parallel", *self.testr_args) + if not self.no_parallel: + testr_ret = self._run_testr("run", "--parallel", *self.testr_args) + else: + testr_ret = self._run_testr("run", *self.testr_args) if testr_ret: raise distutils.errors.DistutilsError( "testr failed (%d)" % testr_ret) diff --git a/pbr/tests/test_setup.py b/pbr/tests/test_setup.py index 11f9a04..d54f4fd 100644 --- a/pbr/tests/test_setup.py +++ b/pbr/tests/test_setup.py @@ -199,7 +199,7 @@ class GitLogsTest(tests.BaseTestCase): self.useFixture(fixtures.FakePopen(lambda proc_args: { "stdout": BytesIO( - self._fake_log_output(proc_args["args"][2], cmd_map)) + self._fake_log_output(' '.join(proc_args["args"]), cmd_map)) })) with open(os.path.join(self.temp_path, "AUTHORS.in"), "w") as auth_fh: diff --git a/tools/integration.sh b/tools/integration.sh index 2bd0b6a..6760292 100644 --- a/tools/integration.sh +++ b/tools/integration.sh @@ -24,7 +24,7 @@ BASE=${BASE:-/opt/stack} REPODIR=${REPODIR:-$BASE/new} # TODO: Figure out how to get this on to the box properly -sudo apt-get install -y --force-yes libxml2-dev libxslt-dev libmysqlclient-dev libpq-dev libnspr4-dev pkg-config libsqlite3-dev libzmq-dev libffi-dev +sudo apt-get install -y --force-yes libxml2-dev libxslt-dev libmysqlclient-dev libpq-dev libnspr4-dev pkg-config libsqlite3-dev libzmq-dev libffi-dev libldap2-dev libsasl2-dev tmpdir=$(mktemp -d) @@ -173,6 +173,13 @@ for PROJECT in $PROJECTS ; do continue fi shortprojectdir=$projectdir/$SHORT_PROJECT + sudo chown -R $USER $REPODIR/$SHORT_PROJECT + (cd $REPODIR/requirements && python update.py $REPODIR/$SHORT_PROJECT) + pushd $REPODIR/$SHORT_PROJECT + if ! git diff --quiet ; then + git commit -a -m'Update requirements' + fi + popd git clone $REPODIR/$SHORT_PROJECT $shortprojectdir sdistvenv=$tmpdir/sdist @@ -30,5 +30,6 @@ commands = commands = {posargs} [flake8] +ignore = H803 exclude = .venv,.tox,dist,doc,*.egg,build show-source = true |