Move write_pbr_json to avoid issues with nose

Put write_pbr_json in pbr.pbr_json so that you do not need to import
pbr.packaging to use it. This avoids python3 errors with nose where nose
is imported by pbr before it is converted to python3 by 2to3 under
python3.

Also port the pbr.git refactor from the master branch.

Co-Authored-By: Jeremy Stanley <fungi@yuggoth.org>
Change-Id: I1c420fed609bc60bbfdf78eb219e067ccab1a61e
(cherry picked from commit 3550e89db4)
This commit is contained in:
Clark Boylan 2014-12-19 09:45:16 -08:00 committed by Jeremy Stanley
parent e7d2825d39
commit 0acee45efb
6 changed files with 350 additions and 254 deletions

276
pbr/git.py Normal file
View File

@ -0,0 +1,276 @@
# Copyright 2011 OpenStack LLC.
# Copyright 2012-2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import unicode_literals
import distutils.errors
from distutils import log
import io
import os
import re
import subprocess
import pkg_resources
from pbr import options
def _run_shell_command(cmd, throw_on_error=False, buffer=True, env=None):
if buffer:
out_location = subprocess.PIPE
err_location = subprocess.PIPE
else:
out_location = None
err_location = None
newenv = os.environ.copy()
if env:
newenv.update(env)
output = subprocess.Popen(cmd,
stdout=out_location,
stderr=err_location,
env=newenv)
out = output.communicate()
if output.returncode and throw_on_error:
raise distutils.errors.DistutilsError(
"%s returned %d" % (cmd, output.returncode))
if len(out) == 0 or not out[0] or not out[0].strip():
return ''
return out[0].strip().decode('utf-8')
def _run_git_command(cmd, git_dir, **kwargs):
if not isinstance(cmd, (list, tuple)):
cmd = [cmd]
return _run_shell_command(
['git', '--git-dir=%s' % git_dir] + cmd, **kwargs)
def _get_git_directory():
return _run_shell_command(['git', 'rev-parse', '--git-dir'])
def _git_is_installed():
try:
# We cannot use 'which git' as it may not be available
# in some distributions, So just try 'git --version'
# to see if we run into trouble
_run_shell_command(['git', '--version'])
except OSError:
return False
return True
def _get_highest_tag(tags):
"""Find the highest tag from a list.
Pass in a list of tag strings and this will return the highest
(latest) as sorted by the pkg_resources version parser.
"""
return max(tags, key=pkg_resources.parse_version)
def _find_git_files(dirname='', git_dir=None):
"""Behave like a file finder entrypoint plugin.
We don't actually use the entrypoints system for this because it runs
at absurd times. We only want to do this when we are building an sdist.
"""
file_list = []
if git_dir is None:
git_dir = _run_git_functions()
if git_dir:
log.info("[pbr] In git context, generating filelist from git")
file_list = _run_git_command(['ls-files', '-z'], git_dir)
file_list = file_list.split(b'\x00'.decode('utf-8'))
return [f for f in file_list if f]
def _get_raw_tag_info(git_dir):
describe = _run_git_command(['describe', '--always'], git_dir)
if "-" in describe:
return describe.rsplit("-", 2)[-2]
if "." in describe:
return 0
return None
def get_is_release(git_dir):
return _get_raw_tag_info(git_dir) == 0
def _run_git_functions():
git_dir = None
if _git_is_installed():
git_dir = _get_git_directory()
return git_dir or None
def get_git_short_sha(git_dir=None):
"""Return the short sha for this repo, if it exists."""
if not git_dir:
git_dir = _run_git_functions()
if git_dir:
return _run_git_command(
['log', '-n1', '--pretty=format:%h'], git_dir)
return None
def _iter_changelog(changelog):
"""Convert a oneline log iterator to formatted strings.
:param changelog: An iterator of one line log entries like
that given by _iter_log_oneline.
:return: An iterator over (release, formatted changelog) tuples.
"""
first_line = True
current_release = None
yield current_release, "CHANGES\n=======\n\n"
for hash, tags, msg in changelog:
if tags:
current_release = _get_highest_tag(tags)
underline = len(current_release) * '-'
if not first_line:
yield current_release, '\n'
yield current_release, (
"%(tag)s\n%(underline)s\n\n" %
dict(tag=current_release, underline=underline))
if not msg.startswith("Merge "):
if msg.endswith("."):
msg = msg[:-1]
yield current_release, "* %(msg)s\n" % dict(msg=msg)
first_line = False
def _iter_log_oneline(git_dir=None, option_dict=None):
"""Iterate over --oneline log entries if possible.
This parses the output into a structured form but does not apply
presentation logic to the output - making it suitable for different
uses.
:return: An iterator of (hash, tags_set, 1st_line) tuples, or None if
changelog generation is disabled / not available.
"""
if not option_dict:
option_dict = {}
should_skip = options.get_boolean_option(option_dict, 'skip_changelog',
'SKIP_WRITE_GIT_CHANGELOG')
if should_skip:
return
if git_dir is None:
git_dir = _get_git_directory()
if not git_dir:
return
return _iter_log_inner(git_dir)
def _iter_log_inner(git_dir):
"""Iterate over --oneline log entries.
This parses the output intro a structured form but does not apply
presentation logic to the output - making it suitable for different
uses.
:return: An iterator of (hash, tags_set, 1st_line) tuples.
"""
log.info('[pbr] Generating ChangeLog')
log_cmd = ['log', '--oneline', '--decorate']
changelog = _run_git_command(log_cmd, git_dir)
for line in changelog.split('\n'):
line_parts = line.split()
if len(line_parts) < 2:
continue
# Tags are in a list contained in ()'s. If a commit
# subject that is tagged happens to have ()'s in it
# this will fail
if line_parts[1].startswith('(') and ')' in line:
msg = line.split(')')[1].strip()
else:
msg = " ".join(line_parts[1:])
if "tag:" in line:
tags = set([
tag.split(",")[0]
for tag in line.split(")")[0].split("tag: ")[1:]])
else:
tags = set()
yield line_parts[0], tags, msg
def write_git_changelog(git_dir=None, dest_dir=os.path.curdir,
option_dict=dict(), changelog=None):
"""Write a changelog based on the git changelog."""
if not changelog:
changelog = _iter_log_oneline(git_dir=git_dir, option_dict=option_dict)
if changelog:
changelog = _iter_changelog(changelog)
if not changelog:
return
log.info('[pbr] Writing ChangeLog')
new_changelog = os.path.join(dest_dir, 'ChangeLog')
# If there's already a ChangeLog and it's not writable, just use it
if (os.path.exists(new_changelog)
and not os.access(new_changelog, os.W_OK)):
return
with io.open(new_changelog, "w", encoding="utf-8") as changelog_file:
for release, content in changelog:
changelog_file.write(content)
def generate_authors(git_dir=None, dest_dir='.', option_dict=dict()):
"""Create AUTHORS file using git commits."""
should_skip = options.get_boolean_option(option_dict, 'skip_authors',
'SKIP_GENERATE_AUTHORS')
if should_skip:
return
old_authors = os.path.join(dest_dir, 'AUTHORS.in')
new_authors = os.path.join(dest_dir, 'AUTHORS')
# If there's already an AUTHORS file and it's not writable, just use it
if (os.path.exists(new_authors)
and not os.access(new_authors, os.W_OK)):
return
log.info('[pbr] Generating AUTHORS')
ignore_emails = '(jenkins@review|infra@lists|jenkins@openstack)'
if git_dir is None:
git_dir = _get_git_directory()
if git_dir:
authors = []
# don't include jenkins email address in AUTHORS file
git_log_cmd = ['log', '--format=%aN <%aE>']
authors += _run_git_command(git_log_cmd, git_dir).split('\n')
authors = [a for a in authors if not re.search(ignore_emails, a)]
# get all co-authors from commit messages
co_authors_out = _run_git_command('log', git_dir)
co_authors = re.findall('Co-authored-by:.+', co_authors_out,
re.MULTILINE)
co_authors = [signed.split(":", 1)[1].strip()
for signed in co_authors if signed]
authors += co_authors
authors = sorted(set(authors))
with open(new_authors, 'wb') as new_authors_fh:
if os.path.exists(old_authors):
with open(old_authors, "rb") as old_authors_fh:
new_authors_fh.write(old_authors_fh.read())
new_authors_fh.write(('\n'.join(authors) + '\n')
.encode('utf-8'))

View File

@ -23,15 +23,11 @@ Utilities with minimum-depends for use in setup.py
from __future__ import unicode_literals
import email
import io
import json
import os
import re
import subprocess
import sys
from distutils.command import install as du_install
import distutils.errors
from distutils import log
import pkg_resources
from setuptools.command import easy_install
@ -41,7 +37,9 @@ from setuptools.command import install_scripts
from setuptools.command import sdist
from pbr import extra_files
from pbr import git
from pbr import options
import pbr.pbr_json
REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires')
TEST_REQUIREMENTS_FILES = ('test-requirements.txt', 'tools/test-requires')
@ -82,7 +80,7 @@ def _pip_install(links, requires, root=None, option_dict=dict()):
cmd.append(link)
# NOTE(ociuhandu): popen on Windows does not accept unicode strings
_run_shell_command(
git._run_shell_command(
cmd + requires,
throw_on_error=True, buffer=False, env=dict(PIP_USE_WHEEL=b"true"))
@ -175,180 +173,6 @@ def parse_dependency_links(requirements_files=None):
return dependency_links
def _run_git_command(cmd, git_dir, **kwargs):
if not isinstance(cmd, (list, tuple)):
cmd = [cmd]
return _run_shell_command(
['git', '--git-dir=%s' % git_dir] + cmd, **kwargs)
def _run_shell_command(cmd, throw_on_error=False, buffer=True, env=None):
if buffer:
out_location = subprocess.PIPE
err_location = subprocess.PIPE
else:
out_location = None
err_location = None
newenv = os.environ.copy()
if env:
newenv.update(env)
output = subprocess.Popen(cmd,
stdout=out_location,
stderr=err_location,
env=newenv)
out = output.communicate()
if output.returncode and throw_on_error:
raise distutils.errors.DistutilsError(
"%s returned %d" % (cmd, output.returncode))
if len(out) == 0 or not out[0] or not out[0].strip():
return ''
return out[0].strip().decode('utf-8')
def _get_git_directory():
return _run_shell_command(['git', 'rev-parse', '--git-dir'])
def _git_is_installed():
try:
# We cannot use 'which git' as it may not be available
# in some distributions, So just try 'git --version'
# to see if we run into trouble
_run_shell_command(['git', '--version'])
except OSError:
return False
return True
def _get_highest_tag(tags):
"""Find the highest tag from a list.
Pass in a list of tag strings and this will return the highest
(latest) as sorted by the pkg_resources version parser.
"""
return max(tags, key=pkg_resources.parse_version)
def write_git_changelog(git_dir=None, dest_dir=os.path.curdir,
option_dict=dict()):
"""Write a changelog based on the git changelog."""
should_skip = options.get_boolean_option(option_dict, 'skip_changelog',
'SKIP_WRITE_GIT_CHANGELOG')
if should_skip:
return
new_changelog = os.path.join(dest_dir, 'ChangeLog')
# If there's already a ChangeLog and it's not writable, just use it
if (os.path.exists(new_changelog)
and not os.access(new_changelog, os.W_OK)):
return
log.info('[pbr] Writing ChangeLog')
if git_dir is None:
git_dir = _run_git_functions()
if not git_dir:
return
log_cmd = ['log', '--oneline', '--decorate']
changelog = _run_git_command(log_cmd, git_dir)
first_line = True
with io.open(new_changelog, "w",
encoding="utf-8") as changelog_file:
changelog_file.write("CHANGES\n=======\n\n")
for line in changelog.split('\n'):
line_parts = line.split()
if len(line_parts) < 2:
continue
# Tags are in a list contained in ()'s. If a commit
# subject that is tagged happens to have ()'s in it
# this will fail
if line_parts[1].startswith('(') and ')' in line:
msg = line.split(')')[1].strip()
else:
msg = " ".join(line_parts[1:])
if "tag:" in line:
tags = [
tag.split(",")[0]
for tag in line.split(")")[0].split("tag: ")[1:]]
tag = _get_highest_tag(tags)
underline = len(tag) * '-'
if not first_line:
changelog_file.write('\n')
changelog_file.write(
("%(tag)s\n%(underline)s\n\n" %
dict(tag=tag,
underline=underline)))
if not msg.startswith("Merge "):
if msg.endswith("."):
msg = msg[:-1]
changelog_file.write(
("* %(msg)s\n" % dict(msg=msg)))
first_line = False
def generate_authors(git_dir=None, dest_dir='.', option_dict=dict()):
"""Create AUTHORS file using git commits."""
should_skip = options.get_boolean_option(option_dict, 'skip_authors',
'SKIP_GENERATE_AUTHORS')
if should_skip:
return
old_authors = os.path.join(dest_dir, 'AUTHORS.in')
new_authors = os.path.join(dest_dir, 'AUTHORS')
# If there's already an AUTHORS file and it's not writable, just use it
if (os.path.exists(new_authors)
and not os.access(new_authors, os.W_OK)):
return
log.info('[pbr] Generating AUTHORS')
ignore_emails = '(jenkins@review|infra@lists|jenkins@openstack)'
if git_dir is None:
git_dir = _run_git_functions()
if git_dir:
authors = []
# don't include jenkins email address in AUTHORS file
git_log_cmd = ['log', '--format=%aN <%aE>']
authors += _run_git_command(git_log_cmd, git_dir).split('\n')
authors = [a for a in authors if not re.search(ignore_emails, a)]
# get all co-authors from commit messages
co_authors_out = _run_git_command('log', git_dir)
co_authors = re.findall('Co-authored-by:.+', co_authors_out,
re.MULTILINE)
co_authors = [signed.split(":", 1)[1].strip()
for signed in co_authors if signed]
authors += co_authors
authors = sorted(set(authors))
with open(new_authors, 'wb') as new_authors_fh:
if os.path.exists(old_authors):
with open(old_authors, "rb") as old_authors_fh:
new_authors_fh.write(old_authors_fh.read())
new_authors_fh.write(('\n'.join(authors) + '\n')
.encode('utf-8'))
def _find_git_files(dirname='', git_dir=None):
"""Behave like a file finder entrypoint plugin.
We don't actually use the entrypoints system for this because it runs
at absurd times. We only want to do this when we are building an sdist.
"""
file_list = []
if git_dir is None and _git_is_installed():
git_dir = _run_git_functions()
if git_dir:
log.info("[pbr] In git context, generating filelist from git")
file_list = _run_git_command(['ls-files', '-z'], git_dir)
file_list = file_list.split(b'\x00'.decode('utf-8'))
return [f for f in file_list if f]
class LocalInstall(install.install):
"""Runs python setup.py install in a sensible manner.
@ -558,7 +382,7 @@ class LocalManifestMaker(egg_info.manifest_maker):
should_skip = options.get_boolean_option(option_dict, 'skip_git_sdist',
'SKIP_GIT_SDIST')
if not should_skip:
rcfiles = _find_git_files()
rcfiles = git._find_git_files()
if rcfiles:
self.filelist.extend(rcfiles)
elif os.path.exists(self.manifest):
@ -601,8 +425,8 @@ class LocalSDist(sdist.sdist):
def run(self):
option_dict = self.distribution.get_option_dict('pbr')
write_git_changelog(option_dict=option_dict)
generate_authors(option_dict=option_dict)
git.write_git_changelog(option_dict=option_dict)
git.generate_authors(option_dict=option_dict)
# sdist.sdist is an old style class, can't use super()
sdist.sdist.run(self)
@ -623,62 +447,19 @@ def have_sphinx():
return _have_sphinx
def _get_raw_tag_info(git_dir):
describe = _run_git_command(['describe', '--always'], git_dir)
if "-" in describe:
return describe.rsplit("-", 2)[-2]
if "." in describe:
return 0
return None
def get_is_release(git_dir):
return _get_raw_tag_info(git_dir) == 0
def _run_git_functions():
git_dir = None
if _git_is_installed():
git_dir = _get_git_directory()
return git_dir or None
def get_git_short_sha(git_dir=None):
"""Return the short sha for this repo, if it exists."""
if not git_dir:
git_dir = _run_git_functions()
if git_dir:
return _run_git_command(
['log', '-n1', '--pretty=format:%h'], git_dir)
return None
def write_pbr_json(cmd, basename, filename):
git_dir = _run_git_functions()
if not git_dir:
return
values = dict()
git_version = get_git_short_sha(git_dir)
is_release = get_is_release(git_dir)
if git_version is not None:
values['git_version'] = git_version
values['is_release'] = is_release
cmd.write_file('pbr', filename, json.dumps(values))
def _get_revno(git_dir):
"""Return the number of commits since the most recent tag.
def _get_revno_and_last_tag(git_dir):
"""Return the commit data about the most recent tag.
We use git-describe to find this out, but if there are no
tags then we fall back to counting commits since the beginning
of time.
"""
raw_tag_info = _get_raw_tag_info(git_dir)
raw_tag_info = git._get_raw_tag_info(git_dir)
if raw_tag_info:
return raw_tag_info
# no tags found
revlist = _run_git_command(
revlist = git._run_git_command(
['rev-list', '--abbrev-commit', 'HEAD'], git_dir)
return len(revlist.splitlines())
@ -689,25 +470,27 @@ def _get_version_from_git(pre_version):
if the current revision has no tag.
"""
git_dir = _run_git_functions()
git_dir = git._run_git_functions()
if git_dir:
if pre_version:
try:
return _run_git_command(
return git._run_git_command(
['describe', '--exact-match'], git_dir,
throw_on_error=True).replace('-', '.')
except Exception:
return "%s.dev%s" % (pre_version, _get_revno(git_dir))
return "%s.dev%s" % (pre_version,
_get_revno_and_last_tag(git_dir)[0])
else:
# git describe always is going to return one of three things
# - a short-sha if there are no tags
# - a tag, if there's one on the current revision
# - a string of the form $last_tag-$revs_since_last_tag-g$short_sha
raw_version = _run_git_command(['describe', '--always'], git_dir)
raw_version = git._run_git_command(['describe', '--always'],
git_dir)
# First, if there are no -'s or .'s, then it's just a short sha.
# Create a synthetic version for it.
if '-' not in raw_version and '.' not in raw_version:
return "0.0.0.post%s" % _get_revno(git_dir)
return "0.0.0.post%s" % _get_revno_and_last_tag(git_dir)[0]
# Now, we want to strip the short-sha prefix
stripped_version = raw_version.split('-g')[0]
# Finally, if we convert - to .post, which will turn the remaining
@ -772,3 +555,10 @@ def get_version(package_name, pre_version=None):
raise Exception("Versioning for this project requires either an sdist"
" tarball, or access to an upstream git repository."
" Are you sure that git is installed?")
# This is added because pbr uses pbr to install itself. That means that
# any changes to the egg info writer entrypoints must be forward and
# backward compatible. This maintains the pbr.packaging.write_pbr_json
# path.
write_pbr_json = pbr.pbr_json.write_pbr_json

32
pbr/pbr_json.py Normal file
View File

@ -0,0 +1,32 @@
# Copyright 2011 OpenStack LLC.
# Copyright 2012-2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
from pbr import git
def write_pbr_json(cmd, basename, filename):
git_dir = git._run_git_functions()
if not git_dir:
return
values = dict()
git_version = git.get_git_short_sha(git_dir)
is_release = git.get_is_release(git_dir)
if git_version is not None:
values['git_version'] = git_version
values['is_release'] = is_release
cmd.write_file('pbr', filename, json.dumps(values))

View File

@ -44,6 +44,7 @@ import tempfile
import fixtures
import mock
from pbr import git
from pbr import packaging
from pbr.tests import base
@ -133,16 +134,14 @@ class TestPackagingInPlainDirectory(base.BaseTestCase):
class TestPresenceOfGit(base.BaseTestCase):
def testGitIsInstalled(self):
with mock.patch.object(packaging,
'_run_shell_command') as _command:
with mock.patch.object(git, '_run_shell_command') as _command:
_command.return_value = 'git version 1.8.4.1'
self.assertEqual(True, packaging._git_is_installed())
self.assertEqual(True, git._git_is_installed())
def testGitIsNotInstalled(self):
with mock.patch.object(packaging,
'_run_shell_command') as _command:
with mock.patch.object(git, '_run_shell_command') as _command:
_command.side_effect = OSError
self.assertEqual(False, packaging._git_is_installed())
self.assertEqual(False, git._git_is_installed())
class TestNestedRequirements(base.BaseTestCase):

View File

@ -32,6 +32,7 @@ except ImportError:
import fixtures
import testscenarios
from pbr import git
from pbr import packaging
from pbr.tests import base
@ -42,35 +43,35 @@ class SkipFileWrites(base.BaseTestCase):
('changelog_option_true',
dict(option_key='skip_changelog', option_value='True',
env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
pkg_func=packaging.write_git_changelog, filename='ChangeLog')),
pkg_func=git.write_git_changelog, filename='ChangeLog')),
('changelog_option_false',
dict(option_key='skip_changelog', option_value='False',
env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None,
pkg_func=packaging.write_git_changelog, filename='ChangeLog')),
pkg_func=git.write_git_changelog, filename='ChangeLog')),
('changelog_env_true',
dict(option_key='skip_changelog', option_value='False',
env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
pkg_func=packaging.write_git_changelog, filename='ChangeLog')),
pkg_func=git.write_git_changelog, filename='ChangeLog')),
('changelog_both_true',
dict(option_key='skip_changelog', option_value='True',
env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True',
pkg_func=packaging.write_git_changelog, filename='ChangeLog')),
pkg_func=git.write_git_changelog, filename='ChangeLog')),
('authors_option_true',
dict(option_key='skip_authors', option_value='True',
env_key='SKIP_GENERATE_AUTHORS', env_value=None,
pkg_func=packaging.generate_authors, filename='AUTHORS')),
pkg_func=git.generate_authors, filename='AUTHORS')),
('authors_option_false',
dict(option_key='skip_authors', option_value='False',
env_key='SKIP_GENERATE_AUTHORS', env_value=None,
pkg_func=packaging.generate_authors, filename='AUTHORS')),
pkg_func=git.generate_authors, filename='AUTHORS')),
('authors_env_true',
dict(option_key='skip_authors', option_value='False',
env_key='SKIP_GENERATE_AUTHORS', env_value='True',
pkg_func=packaging.generate_authors, filename='AUTHORS')),
pkg_func=git.generate_authors, filename='AUTHORS')),
('authors_both_true',
dict(option_key='skip_authors', option_value='True',
env_key='SKIP_GENERATE_AUTHORS', env_value='True',
pkg_func=packaging.generate_authors, filename='AUTHORS')),
pkg_func=git.generate_authors, filename='AUTHORS')),
]
def setUp(self):
@ -129,8 +130,7 @@ class GitLogsTest(base.BaseTestCase):
"stdout": BytesIO(_changelog_content.encode('utf-8'))
}))
packaging.write_git_changelog(git_dir=self.git_dir,
dest_dir=self.temp_path)
git.write_git_changelog(git_dir=self.git_dir, dest_dir=self.temp_path)
with open(os.path.join(self.temp_path, "ChangeLog"), "r") as ch_fh:
changelog_contents = ch_fh.read()
@ -171,14 +171,13 @@ class GitLogsTest(base.BaseTestCase):
return cmd_map[" ".join(cmd)]
self.useFixture(fixtures.MonkeyPatch(
"pbr.packaging._run_shell_command",
"pbr.git._run_shell_command",
_fake_run_shell_command))
with open(os.path.join(self.temp_path, "AUTHORS.in"), "w") as auth_fh:
auth_fh.write("%s\n" % author_old)
packaging.generate_authors(git_dir=self.git_dir,
dest_dir=self.temp_path)
git.generate_authors(git_dir=self.git_dir, dest_dir=self.temp_path)
with open(os.path.join(self.temp_path, "AUTHORS"), "r") as auth_fh:
authors = auth_fh.read()

View File

@ -39,7 +39,7 @@ distutils.setup_keywords =
distutils.commands =
testr = pbr.testr_command:Testr
egg_info.writers =
pbr.json = pbr.packaging:write_pbr_json
pbr.json = pbr.pbr_json:write_pbr_json
console_scripts =
pbr = pbr.cmd.main:main