Changeset - d6d3cb5991e2
[Not reviewed]
stable
0 1 0
Mads Kiilerich (mads) - 3 years ago 2023-04-20 00:30:29
mads@kiilerich.com
tests: stabilize Git committer in test_vcs_operations

Git tries to find out name and email in this order:

1. The author can be set e.g. via the `--author` option of `git commit`.
2. If set, the environment variables GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL,
GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL are taken.
3. If set, various (global) config files are considered.
4. Unless disabled by the user.useconfigonly config, the names and emails are
inferred from various system sources such as various fields from /etc/passwd,
/etc/mailname and the environment variable EMAIL.

The author can be provided on the command line (1), but that is not possible
for the committer.

It is not an option to modify Git’s configuration files, so the result of (3)
depends on the system the tests run on, which should be avoided. A follow-up
patch will try to instruct Git to not read the system Git configuration files.

(4) is also system-dependent. On some systems, (4) is disabled in the Git
configuration. If enabled, Git will try to infer the committer name from the
gecko field in /etc/passwd, but will fail if it is empty. The previous code
passed the environment variable EMAIL to provide the corresponding email
address.

By passing the names and emails via (2), we can set the author and committer
name and email uniformly and prevent Git from using the system-dependent ways
(3) and (4). This will replace the use of of EMAIL. The environment variables
were introduced in 2005, so there should be no backwards compatibility
problems.

The tests will specify --author explicitly in the cases where the actual name
matters. We just need default values that can be used for committing when we
don't care.

We set it as static defaults to:
Author: test_regular <test_regular@example.com>
Commit: test_admin <test_admin@example.com>

Based on changes and research by Manuel Jacob <me@manueljacob.de>.
1 file changed with 6 insertions and 3 deletions:
0 comments (0 inline, 0 general)
kallithea/tests/other/test_vcs_operations.py
Show inline comments
 
@@ -129,95 +129,98 @@ parametrize_vcs_test_hg = base.parametri
 
parametrize_vcs_test_http = base.parametrize('vt', [
 
    HgHttpVcsTest,
 
    GitHttpVcsTest,
 
])
 

	
 
class Command(object):
 

	
 
    def __init__(self, cwd):
 
        self.cwd = cwd
 

	
 
    def execute(self, *args, **environ):
 
        """
 
        Runs command on the system with given ``args`` using simple space
 
        join without safe quoting.
 
        """
 
        command = ' '.join(args)
 
        ignoreReturnCode = environ.pop('ignoreReturnCode', False)
 
        if DEBUG:
 
            print('*** CMD %s ***' % command)
 
        testenv = dict(os.environ)
 
        testenv['LANG'] = 'en_US.UTF-8'
 
        testenv['LANGUAGE'] = 'en_US:en'
 
        testenv['HGPLAIN'] = ''
 
        testenv['HGRCPATH'] = ''
 
        testenv['GIT_COMMITTER_NAME'] = base.TEST_USER_ADMIN_LOGIN
 
        testenv['GIT_COMMITTER_EMAIL'] = base.TEST_USER_ADMIN_EMAIL
 
        testenv['GIT_AUTHOR_NAME'] = base.TEST_USER_REGULAR_LOGIN
 
        testenv['GIT_AUTHOR_EMAIL'] = base.TEST_USER_REGULAR_EMAIL
 
        testenv.update(environ)
 
        p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd, env=testenv)
 
        stdout, stderr = p.communicate()
 
        if DEBUG:
 
            if stdout:
 
                print('stdout:', stdout)
 
            if stderr:
 
                print('stderr:', stderr)
 
        if not ignoreReturnCode:
 
            assert p.returncode == 0
 
        return safe_str(stdout), safe_str(stderr)
 

	
 

	
 
def _get_tmp_dir(prefix='vcs_operations-', suffix=''):
 
    return tempfile.mkdtemp(dir=base.TESTS_TMP_PATH, prefix=prefix, suffix=suffix)
 

	
 

	
 
def _add_files(vcs, dest_dir, files_no=3):
 
    """
 
    Generate some files, add it to dest_dir repo and push back
 
    vcs is git or hg and defines what VCS we want to make those files for
 

	
 
    :param vcs:
 
    :param dest_dir:
 
    """
 
    added_file = '%ssetup.py' % next(_RandomNameSequence())
 
    open(os.path.join(dest_dir, added_file), 'a').close()
 
    Command(dest_dir).execute(vcs, 'add', added_file)
 

	
 
    email = 'me@example.com'
 
    if os.name == 'nt':
 
        author_str = 'User <%s>' % email
 
    else:
 
        author_str = 'User ǝɯɐᴎ <%s>' % email
 
    for i in range(files_no):
 
        cmd = """echo "added_line%s" >> %s""" % (i, added_file)
 
        Command(dest_dir).execute(cmd)
 
        if vcs == 'hg':
 
            cmd = """hg commit -m "committed new %s" -u "%s" "%s" """ % (
 
                i, author_str, added_file
 
            )
 
        elif vcs == 'git':
 
            cmd = """git commit -m "committed new %s" --author "%s" "%s" """ % (
 
                i, author_str, added_file
 
            )
 
        # git commit needs EMAIL on some machines
 
        Command(dest_dir).execute(cmd, EMAIL=email)
 
        Command(dest_dir).execute(cmd)
 

	
 
def _add_files_and_push(webserver, vt, dest_dir, clone_url, ignoreReturnCode=False, files_no=3):
 
    _add_files(vt.repo_type, dest_dir, files_no=files_no)
 
    # PUSH it back
 
    stdout = stderr = None
 
    if vt.repo_type == 'hg':
 
        stdout, stderr = Command(dest_dir).execute('hg push -f --verbose', clone_url, ignoreReturnCode=ignoreReturnCode)
 
    elif vt.repo_type == 'git':
 
        stdout, stderr = Command(dest_dir).execute('git push -f --verbose', clone_url, "master", ignoreReturnCode=ignoreReturnCode)
 

	
 
    return stdout, stderr
 

	
 

	
 
def _check_outgoing(vcs, cwd, clone_url):
 
    if vcs == 'hg':
 
        # hg removes the password from default URLs, so we have to provide it here via the clone_url
 
        return Command(cwd).execute('hg -q outgoing', clone_url, ignoreReturnCode=True)
 
    elif vcs == 'git':
 
        Command(cwd).execute('git remote update')
 
        return Command(cwd).execute('git log origin/master..master')
 

	
 

	
 
def set_anonymous_access(enable=True):
 
    user = db.User.get_default_user()
 
@@ -597,45 +600,45 @@ class TestVCSOperations(base.TestControl
 
        assert stdout != ''
 

	
 
        # set prechangegroup hook to method that returns False
 
        db.Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.passing_test_hook')
 
        meta.Session().commit()
 
        # re-try to push
 
        stdout, stderr = Command(dest_dir).execute('%s push' % vt.repo_type, clone_url, ignoreReturnCode=True)
 
        assert 'passing_test_hook succeeded' in stdout + stderr
 
        assert 'Traceback' not in stdout + stderr
 
        assert 'prechangegroup.testhook hook failed' not in stdout + stderr
 
        # no more outgoing changesets
 
        stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
 
        assert stdout == ''
 
        assert stderr == ''
 

	
 
    def test_add_submodule_git(self, webserver, testfork):
 
        dest_dir = _get_tmp_dir()
 
        clone_url = GitHttpVcsTest.repo_url_param(webserver, base.GIT_REPO)
 

	
 
        fork_url = GitHttpVcsTest.repo_url_param(webserver, testfork['git'])
 

	
 
        # add submodule
 
        stdout, stderr = Command(base.TESTS_TMP_PATH).execute('git clone', fork_url, dest_dir)
 
        stdout, stderr = Command(dest_dir).execute('git submodule add', clone_url, 'testsubmodule')
 
        stdout, stderr = Command(dest_dir).execute('git commit -am "added testsubmodule pointing to', clone_url, '"', EMAIL=base.TEST_USER_ADMIN_EMAIL)
 
        stdout, stderr = Command(dest_dir).execute('git commit -am "added testsubmodule pointing to', clone_url, '"')
 
        stdout, stderr = Command(dest_dir).execute('git push', fork_url, 'master')
 

	
 
        # check for testsubmodule link in files page
 
        self.log_user()
 
        response = self.app.get(base.url(controller='files', action='index',
 
                                    repo_name=testfork['git'],
 
                                    revision='tip',
 
                                    f_path='/'))
 
        # check _repo_files_url that will be used to reload as AJAX
 
        response.mustcontain('var _repo_files_url = ("/%s/files/");' % testfork['git'])
 

	
 
        response.mustcontain('<a class="submodule-dir" href="%s" target="_blank"><i class="icon-file-submodule"></i><span>testsubmodule @ ' % clone_url)
 

	
 
        # check that following a submodule link actually works - and redirects
 
        response = self.app.get(base.url(controller='files', action='index',
 
                                    repo_name=testfork['git'],
 
                                    revision='tip',
 
                                    f_path='/testsubmodule'),
 
                                status=302)
 
        assert response.location == clone_url
0 comments (0 inline, 0 general)