Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ansible-core-2.19 for 
openSUSE:Factory checked in at 2026-11-06 19:55:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ansible-core-2.19 (Old)
 and      /work/SRC/openSUSE:Factory/.ansible-core-2.19.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ansible-core-2.19"

Fri Nov  6 19:55:32 2026 rev:14 rq:1395744 version:2.19.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/ansible-core-2.19/ansible-core-2.19.changes      
2026-10-18 19:25:19.513788529 +0200
+++ 
/work/SRC/openSUSE:Factory/.ansible-core-2.19.new.3759290/ansible-core-2.19.changes
 2026-11-06 20:00:55.402592324 +0100
@@ -1,0 +2,18 @@
+Fri Nov  6 08:45:59 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 2.19.15:
+  
https://github.com/ansible/ansible/blob/v2.19.15/changelogs/CHANGELOG-v2.19.rst
+  * Minor Changes
+    - ansible-test - Remove unsupported FreeBSD 13.5 remote.
+  * Security Fixes
+    - ansible-galaxy collection install - fix validating FILES.json
+      entries are contained in the collection before creating them.
+      (CVE-2026-89091)
+    - ansible-galaxy role install - fix validating the role name is
+      contained to the configured role path. (CVE-2026-105929)
+  * Bugfixes
+    - git module - updated to avoid possible incorrect parameters
+      read from the repo targets. CVE-2026-84503
+- remove patch ansible-core-CVE-2026-89091.patch
+
+-------------------------------------------------------------------

Old:
----
  ansible-core-CVE-2026-89091.patch
  ansible_core-2.19.14.tar.gz
  ansible_core-2.19.14.tar.gz.sha256

New:
----
  ansible_core-2.19.15.tar.gz
  ansible_core-2.19.15.tar.gz.sha256

----------(Old B)----------
  Old:      read from the repo targets. CVE-2026-84503
- remove patch ansible-core-CVE-2026-89091.patch
----------(Old E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ansible-core-2.19.spec ++++++
--- /var/tmp/diff_new_pack.oqkkwr/_old  2026-11-06 20:00:57.253676504 +0100
+++ /var/tmp/diff_new_pack.oqkkwr/_new  2026-11-06 20:00:57.257676686 +0100
@@ -43,7 +43,7 @@
 %endif
 
 Name:           ansible-core-2.19
-Version:        2.19.14
+Version:        2.19.15
 Release:        0
 Summary:        Radically simple IT automation
 License:        GPL-3.0-or-later
@@ -52,8 +52,6 @@
 Source1:        ansible_core-%{version}.tar.gz.sha256
 # CVE-2026-16493 (bsc#1272369)
 Patch0:         ansible-core-CVE-2026-16493.patch
-# CVE-2026-89091 (bsc#1284847)
-Patch1:         ansible-core-CVE-2026-89091.patch
 BuildArch:      noarch
 
 Provides:       ansible-core = %{version}

++++++ ansible_core-2.19.14.tar.gz -> ansible_core-2.19.15.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/PKG-INFO 
new/ansible_core-2.19.15/PKG-INFO
--- old/ansible_core-2.19.14/PKG-INFO   2026-10-05 17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/PKG-INFO   2026-11-02 18:10:40.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.19.14
+Version: 2.19.15
 Summary: Radically simple IT automation
 Author: Ansible Project
 Project-URL: Homepage, https://ansible.com/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/ansible_core.egg-info/PKG-INFO 
new/ansible_core-2.19.15/ansible_core.egg-info/PKG-INFO
--- old/ansible_core-2.19.14/ansible_core.egg-info/PKG-INFO     2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/ansible_core.egg-info/PKG-INFO     2026-11-02 
18:10:40.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: ansible-core
-Version: 2.19.14
+Version: 2.19.15
 Summary: Radically simple IT automation
 Author: Ansible Project
 Project-URL: Homepage, https://ansible.com/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/ansible_core.egg-info/SOURCES.txt 
new/ansible_core-2.19.15/ansible_core.egg-info/SOURCES.txt
--- old/ansible_core-2.19.14/ansible_core.egg-info/SOURCES.txt  2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/ansible_core.egg-info/SOURCES.txt  2026-11-02 
18:10:40.000000000 +0100
@@ -993,11 +993,13 @@
 test/integration/targets/ansible-galaxy-collection/library/setup_collections.py
 test/integration/targets/ansible-galaxy-collection/meta/main.yml
 test/integration/targets/ansible-galaxy-collection/tasks/build.yml
+test/integration/targets/ansible-galaxy-collection/tasks/build_and_install_tarball.yml
 test/integration/targets/ansible-galaxy-collection/tasks/download.yml
 
test/integration/targets/ansible-galaxy-collection/tasks/fail_fast_resolvelib.yml
 test/integration/targets/ansible-galaxy-collection/tasks/init.yml
 test/integration/targets/ansible-galaxy-collection/tasks/install.yml
 test/integration/targets/ansible-galaxy-collection/tasks/install_offline.yml
+test/integration/targets/ansible-galaxy-collection/tasks/install_tarball.yml
 test/integration/targets/ansible-galaxy-collection/tasks/list.yml
 test/integration/targets/ansible-galaxy-collection/tasks/main.yml
 
test/integration/targets/ansible-galaxy-collection/tasks/pinned_pre_releases_in_deptree.yml
@@ -4897,7 +4899,6 @@
 test/units/cli/test_playbook.py
 test/units/cli/test_vault.py
 test/units/cli/arguments/test_option_helpers.py
-test/units/cli/galaxy/test_collection_extract_tar.py
 test/units/cli/galaxy/test_display_collection.py
 test/units/cli/galaxy/test_display_header.py
 test/units/cli/galaxy/test_display_role.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/changelogs/CHANGELOG-v2.19.rst 
new/ansible_core-2.19.15/changelogs/CHANGELOG-v2.19.rst
--- old/ansible_core-2.19.14/changelogs/CHANGELOG-v2.19.rst     2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/changelogs/CHANGELOG-v2.19.rst     2026-11-02 
18:10:40.000000000 +0100
@@ -4,6 +4,31 @@
 
 .. contents:: Topics
 
+v2.19.15
+========
+
+Release Summary
+---------------
+
+| Release Date: 2026-11-02
+| `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+Minor Changes
+-------------
+
+- ansible-test - Remove unsupported FreeBSD 13.5 remote.
+
+Security Fixes
+--------------
+
+- ``ansible-galaxy collection install`` - fix validating ``FILES.json`` 
entries are contained in the collection before creating them. (CVE-2026-89091)
+- ``ansible-galaxy role install`` - fix validating the role name is contained 
to the configured role path. (CVE-2026-105929)
+
+Bugfixes
+--------
+
+- git module - updated to avoid possible incorrect parameters read from the 
repo targets. CVE-2026-84503
+
 v2.19.14
 ========
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/changelogs/changelog.yaml 
new/ansible_core-2.19.15/changelogs/changelog.yaml
--- old/ansible_core-2.19.14/changelogs/changelog.yaml  2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/changelogs/changelog.yaml  2026-11-02 
18:10:40.000000000 +0100
@@ -1391,6 +1391,42 @@
     - ansible-test-validate-modules-secret.yml
     - ensure_conn_cli_dir_perms.yml
     release_date: '2026-09-29'
+  2.19.15:
+    changes:
+      release_summary: '| Release Date: 2026-11-02
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+        '
+    codename: What Is and What Should Never Be
+    fragments:
+    - 2.19.15_summary.yaml
+    release_date: '2026-11-02'
+  2.19.15rc1:
+    changes:
+      bugfixes:
+      - git module - updated to avoid possible incorrect parameters read from 
the
+        repo targets. CVE-2026-84503
+      minor_changes:
+      - ansible-test - Remove unsupported FreeBSD 13.5 remote.
+      release_summary: '| Release Date: 2026-10-27
+
+        | `Porting Guide 
<https://docs.ansible.com/ansible-core/2.19/porting_guides/porting_guide_core_2.19.html>`__
+
+        '
+      security_fixes:
+      - '``ansible-galaxy collection install`` - fix validating ``FILES.json`` 
entries
+        are contained in the collection before creating them. (CVE-2026-89091)'
+      - '``ansible-galaxy role install`` - fix validating the role name is 
contained
+        to the configured role path. (CVE-2026-105929)'
+    codename: What Is and What Should Never Be
+    fragments:
+    - 2.19.15rc1_summary.yaml
+    - ansible-galaxy-collection-check-path-containment.yml
+    - ansible-galaxy-role-name-containment.yml
+    - ansible-test-remove-freebsd-13.5.yml
+    - git_fixes.yml
+    release_date: '2026-10-27'
   2.19.1rc1:
     changes:
       bugfixes:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/lib/ansible/cli/galaxy.py 
new/ansible_core-2.19.15/lib/ansible/cli/galaxy.py
--- old/ansible_core-2.19.14/lib/ansible/cli/galaxy.py  2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/lib/ansible/cli/galaxy.py  2026-11-02 
18:10:40.000000000 +0100
@@ -61,6 +61,7 @@
 from ansible.template import trust_as_template
 from ansible.utils.collection_loader import AnsibleCollectionConfig
 from ansible.utils.display import Display
+from ansible.utils.path import is_subpath
 from ansible.utils.plugin_docs import get_versioned_doclink
 from ansible.utils.vars import load_extra_vars
 
@@ -1471,6 +1472,15 @@
 
             display.vvv('Processing role %s ' % role.name)
 
+            if not any(
+                is_subpath(os.path.join(path, role.name), path, real=True)
+                for path in context.CLIARGS['roles_path']
+            ):
+                display.warning(f"The role name '{role.name}' resolves to a 
path outside of the configured role directory")
+                self.exit_without_ignore()
+                display.display(f'- skipping role {role.name}')
+                continue
+
             # query the galaxy API for the role data
 
             if role.install_info is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/lib/ansible/galaxy/collection/__init__.py 
new/ansible_core-2.19.15/lib/ansible/galaxy/collection/__init__.py
--- old/ansible_core-2.19.14/lib/ansible/galaxy/collection/__init__.py  
2026-10-05 17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/lib/ansible/galaxy/collection/__init__.py  
2026-11-02 18:10:40.000000000 +0100
@@ -1685,6 +1685,9 @@
     except KeyError:
         raise AnsibleError("Unable to extract '%s' from collection" % dirname)
 
+    if not _is_child_path(to_bytes(tar_member.name, 
errors='surrogate_or_strict'), b_dest):
+        raise AnsibleError(f"Cannot extract directory '{dirname}' in 
collection: path is outside of collection '{tar_member.name}'")
+
     b_dir_path = os.path.join(b_dest, to_bytes(dirname, 
errors='surrogate_or_strict'))
 
     b_parent_path = os.path.dirname(b_dir_path)
@@ -1789,13 +1792,16 @@
 def _is_child_path(path, parent_path, link_name=None):
     """ Checks that path is a path within the parent_path specified. """
     b_path = to_bytes(path, errors='surrogate_or_strict')
+    b_parent_path = to_bytes(parent_path, errors='surrogate_or_strict')
 
     if link_name and not os.path.isabs(b_path):
         # If link_name is specified, path is the source of the link and we 
need to resolve the absolute path.
         b_link_dir = os.path.dirname(to_bytes(link_name, 
errors='surrogate_or_strict'))
-        b_path = os.path.abspath(os.path.join(b_link_dir, b_path))
+        b_path = os.path.join(b_link_dir, b_path)
+    elif not os.path.isabs(b_path):
+        b_path = os.path.join(b_parent_path, b_path)
 
-    b_parent_path = to_bytes(parent_path, errors='surrogate_or_strict')
+    b_path = os.path.normpath(b_path)
     return b_path == b_parent_path or b_path.startswith(b_parent_path + 
to_bytes(os.path.sep))
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/lib/ansible/module_utils/ansible_release.py 
new/ansible_core-2.19.15/lib/ansible/module_utils/ansible_release.py
--- old/ansible_core-2.19.14/lib/ansible/module_utils/ansible_release.py        
2026-10-05 17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/lib/ansible/module_utils/ansible_release.py        
2026-11-02 18:10:40.000000000 +0100
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.19.14'
+__version__ = '2.19.15'
 __author__ = 'Ansible, Inc.'
 __codename__ = "What Is and What Should Never Be"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/lib/ansible/modules/git.py 
new/ansible_core-2.19.15/lib/ansible/modules/git.py
--- old/ansible_core-2.19.14/lib/ansible/modules/git.py 2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/lib/ansible/modules/git.py 2026-11-02 
18:10:40.000000000 +0100
@@ -379,14 +379,14 @@
                 module.fail_json(msg="Unable to read %s" % headfile)
         if rawdata:
             try:
-                rawdata = rawdata.replace('refs/remotes/%s' % remote, '', 1)
+                rawdata = rawdata.replace(f'refs/remotes/{remote}', '', 1)
                 refparts = rawdata.split(' ')
                 newref = refparts[-1]
                 nrefparts = newref.split('/', 2)
                 res = nrefparts[-1].rstrip('\n')
             except Exception:
                 if fail_on_error and module:
-                    module.fail_json(msg="Unable to split head from '%s'" % 
rawdata)
+                    module.fail_json(msg=f"Unable to split head from 
'{rawdata}'")
     return res
 
 
@@ -406,7 +406,7 @@
     params = []
 
     # run a bad submodule command to get valid params
-    cmd = "%s submodule update --help" % (git_path)
+    cmd = [git_path, 'submodule', 'update', '--help']
     rc, stdout, stderr = module.run_command(cmd, cwd=cwd)
     lines = stderr.split('\n')
     update_line = None
@@ -519,7 +519,7 @@
 def get_version(module, git_path, dest, ref="HEAD"):
     """ samples the version of the git repo """
 
-    cmd = "%s rev-parse %s" % (git_path, ref)
+    cmd = [git_path, "rev-parse", ref]
     rc, stdout, stderr = module.run_command(cmd, cwd=dest)
     sha = to_native(stdout).rstrip('\n')
     return sha
@@ -617,7 +617,7 @@
             # git before 1.7.5 doesn't have separate-git-dir argument, do 
fallback
             needs_separate_git_dir_fallback = True
         else:
-            cmd.append('--separate-git-dir=%s' % separate_git_dir)
+            cmd.append(f'--separate-git-dir={separate_git_dir}')
 
     cmd.extend([repo, dest])
     module.run_command(cmd, check_rc=True, cwd=dest_dirname)
@@ -642,7 +642,7 @@
     if bare:
         return False
 
-    cmd = "%s status --porcelain" % (git_path)
+    cmd = [git_path, "status", "--porcelain"]
     rc, stdout, stderr = module.run_command(cmd, cwd=dest)
     lines = stdout.splitlines()
     lines = list(filter(lambda c: not re.search('^\\?\\?.*$', c), lines))
@@ -656,7 +656,7 @@
     Discards any changes to tracked files in working
     tree since that commit.
     """
-    cmd = "%s reset --hard HEAD" % (git_path,)
+    cmd = [git_path, "reset", "--hard", "HEAD"]
     return module.run_command(cmd, check_rc=True, cwd=dest)
 
 
@@ -668,7 +668,7 @@
         # Ensure we have the object we are referring to during git diff !
         git_version_used = git_version(git_path, module)
         fetch(git_path, module, repo, dest, after, remote, depth, bare, '', 
git_version_used)
-        cmd = '%s diff %s %s' % (git_path, before, after)
+        cmd = [git_path, 'diff', before, after]
         (rc, out, err) = module.run_command(cmd, cwd=dest)
         if rc == 0 and out:
             return {'prepared': out}
@@ -685,6 +685,7 @@
     cloning = False
     cwd = None
     tag = False
+    cmd = [git_path, 'ls-remote', remote]
     if remote == module.params['repo']:
         cloning = True
     elif remote == 'file://' + os.path.expanduser(module.params['repo']):
@@ -694,15 +695,15 @@
     if version == 'HEAD':
         if cloning:
             # cloning the repo, just get the remote's HEAD version
-            cmd = '%s ls-remote %s -h HEAD' % (git_path, remote)
+            cmd.extend(['-h', 'HEAD'])
         else:
             head_branch = get_head_branch(git_path, module, dest, remote, bare)
-            cmd = '%s ls-remote %s -h refs/heads/%s' % (git_path, remote, 
head_branch)
+            cmd.extend(['-h', '--', shlex.quote(f'refs/heads/{head_branch}')])
     elif is_remote_branch(git_path, module, dest, remote, version):
-        cmd = '%s ls-remote %s -h refs/heads/%s' % (git_path, remote, version)
+        cmd.extend(['-h', f'refs/heads/{version}'])
     elif is_remote_tag(git_path, module, dest, remote, version):
         tag = True
-        cmd = '%s ls-remote %s -t refs/tags/%s*' % (git_path, remote, version)
+        cmd.extend(['-t', f'refs/tags/{version}*'])
     else:
         # appears to be a sha1.  return as-is since it appears
         # cannot check for a specific sha1 on remote
@@ -727,7 +728,7 @@
 
 
 def is_remote_tag(git_path, module, dest, remote, version):
-    cmd = '%s ls-remote %s -t refs/tags/%s' % (git_path, remote, version)
+    cmd = [git_path, 'ls-remote', remote, '-t', f'refs/tags/{version}']
     (rc, out, err) = module.run_command(cmd, check_rc=True, cwd=dest)
     if to_native(version, errors='surrogate_or_strict') in out:
         return True
@@ -737,10 +738,10 @@
 
 def get_branches(git_path, module, dest):
     branches = []
-    cmd = '%s branch --no-color -a' % (git_path,)
+    cmd = [git_path, 'branch', '--no-color', '-a']
     (rc, out, err) = module.run_command(cmd, cwd=dest)
     if rc != 0:
-        module.fail_json(msg="Could not determine branch data - received %s" % 
out, stdout=out, stderr=err)
+        module.fail_json(msg=f"Could not determine branch data - received 
{out}", stdout=out, stderr=err)
     for line in out.split('\n'):
         if line.strip():
             branches.append(line.strip())
@@ -752,7 +753,7 @@
     cmd = [git_path, 'for-each-ref', 'refs/tags/', '--format', 
'%(objecttype):%(refname:short)']
     (rc, out, err) = module.run_command(cmd, cwd=dest)
     if rc != 0:
-        module.fail_json(msg="Could not determine tag data - received %s" % 
out, stdout=out, stderr=err)
+        module.fail_json(msg=f"Could not determine tag data - received {out}", 
stdout=out, stderr=err)
     for line in to_native(out).split('\n'):
         if line.strip():
             tagtype, tagname = line.strip().split(':')
@@ -762,7 +763,7 @@
 
 
 def is_remote_branch(git_path, module, dest, remote, version):
-    cmd = '%s ls-remote %s -h refs/heads/%s' % (git_path, remote, version)
+    cmd = [git_path, 'ls-remote', remote, '-h', f'refs/heads/{version}']
     (rc, out, err) = module.run_command(cmd, check_rc=True, cwd=dest)
     if to_native(version, errors='surrogate_or_strict') in out:
         return True
@@ -772,13 +773,7 @@
 
 def is_local_branch(git_path, module, dest, branch):
     branches = get_branches(git_path, module, dest)
-    lbranch = '%s' % branch
-    if lbranch in branches:
-        return True
-    elif '* %s' % branch in branches:
-        return True
-    else:
-        return False
+    return f'{branch}' in branches or f'* {branch}' in branches
 
 
 def is_not_a_branch(git_path, module, dest):
@@ -840,6 +835,11 @@
     if is_not_a_branch(git_path, module, dest):
         headfile = os.path.join(repo_path, 'refs', 'remotes', remote, 'HEAD')
     branch = head_splitter(headfile, remote, module=module, fail_on_error=True)
+
+    if branch.startswith('-'):
+        # prevent branch names that can be confused as options
+        module.fail_json(msg=f'Invalid branch name ({branch}) from {headfile} 
in {remote}')
+
     return branch
 
 
@@ -963,7 +963,7 @@
             # Compare against submodule HEAD
             # FIXME: determine this from .gitmodules
             version = 'master'
-            after = get_submodule_versions(git_path, module, dest, '%s/%s' % 
(remote, version))
+            after = get_submodule_versions(git_path, module, dest, 
shlex.quote('%s/%s') % (remote, version))
             if begin != after:
                 changed = True
         else:
@@ -1009,48 +1009,52 @@
     Can't use git remote set-branches, as it is not available in git 1.7.1 
(centos6)
     """
 
-    branchref = "+refs/heads/%s:refs/heads/%s" % (version, version)
-    branchref += ' +refs/heads/%s:refs/remotes/%s/%s' % (version, remote, 
version)
-    cmd = "%s fetch --depth=%s %s %s" % (git_path, depth, remote, branchref)
+    cmd = [
+        git_path,
+        "fetch",
+        f"--depth={depth}",
+        remote,
+        f"+refs/heads/{version}:refs/heads/{version}",
+        f"+refs/heads/{version}:refs/remotes/{remote}/{version}",
+    ]
     (rc, out, err) = module.run_command(cmd, cwd=dest)
     if rc != 0:
-        module.fail_json(msg="Failed to fetch branch from remote: %s" % 
version, stdout=out, stderr=err, rc=rc)
+        module.fail_json(msg=f"Failed to fetch branch from remote: {version}", 
stdout=out, stderr=err, rc=rc)
 
 
 def switch_version(git_path, module, dest, remote, version, verify_commit, 
depth, gpg_allowlist):
     cmd = ''
     if version == 'HEAD':
         branch = get_head_branch(git_path, module, dest, remote)
-        (rc, out, err) = module.run_command("%s checkout --force %s" % 
(git_path, branch), cwd=dest)
+        (rc, out, err) = module.run_command([git_path, "checkout", "--force", 
branch], cwd=dest)
         if rc != 0:
-            module.fail_json(msg="Failed to checkout branch %s" % branch,
-                             stdout=out, stderr=err, rc=rc)
-        cmd = "%s reset --hard %s/%s --" % (git_path, remote, branch)
+            module.fail_json(msg=f"Failed to checkout branch {branch} HEAD", 
stdout=out, stderr=err, rc=rc)
+        cmd = [git_path, "reset", "--hard", shlex.quote("/".join([remote, 
branch]))]
     else:
         # FIXME check for local_branch first, should have been fetched already
         if is_remote_branch(git_path, module, dest, remote, version):
+            rv = "/".join([remote, version])
             if depth and not is_local_branch(git_path, module, dest, version):
                 # git clone --depth implies --single-branch, which makes
                 # the checkout fail if the version changes
                 # fetch the remote branch, to be able to check it out next
                 set_remote_branch(git_path, module, dest, remote, version, 
depth)
             if not is_local_branch(git_path, module, dest, version):
-                cmd = "%s checkout --track -b %s %s/%s" % (git_path, version, 
remote, version)
+                cmd = [git_path, "checkout", "--track", "-b", version, rv]
             else:
-                (rc, out, err) = module.run_command("%s checkout --force %s" % 
(git_path, version), cwd=dest)
+                (rc, out, err) = module.run_command([git_path, "checkout", 
"--force", version], cwd=dest)
                 if rc != 0:
                     module.fail_json(msg="Failed to checkout branch %s" % 
version, stdout=out, stderr=err, rc=rc)
-                cmd = "%s reset --hard %s/%s" % (git_path, remote, version)
+                cmd = [git_path, "reset", "--hard", rv]
         else:
-            cmd = "%s checkout --force %s" % (git_path, version)
+            cmd = [git_path, "checkout", "--force", version]
     (rc, out1, err1) = module.run_command(cmd, cwd=dest)
     if rc != 0:
-        if version != 'HEAD':
-            module.fail_json(msg="Failed to checkout %s" % (version),
-                             stdout=out1, stderr=err1, rc=rc, cmd=cmd)
+        if version == 'HEAD':
+            msg = f"Failed to checkout branch {branch}"
         else:
-            module.fail_json(msg="Failed to checkout branch %s" % (branch),
-                             stdout=out1, stderr=err1, rc=rc, cmd=cmd)
+            msg = f"Failed to checkout {version}"
+        module.fail_json(msg=msg, stdout=out1, stderr=err1, rc=rc, cmd=cmd)
 
     if verify_commit:
         verify_commit_sign(git_path, module, dest, version, gpg_allowlist)
@@ -1063,9 +1067,9 @@
         git_sub = "verify-tag"
     else:
         git_sub = "verify-commit"
-    cmd = "%s %s %s" % (git_path, git_sub, version)
+    cmd = [git_path, git_sub, version]
     if gpg_allowlist:
-        cmd += " --raw"
+        cmd.append("--raw")
     (rc, out, err) = module.run_command(cmd, cwd=dest)
     if rc != 0:
         module.fail_json(msg='Failed to verify GPG signature of commit/tag 
"%s"' % version, stdout=out, stderr=err, rc=rc)
@@ -1094,7 +1098,7 @@
 
 def git_version(git_path, module):
     """return the installed version of git"""
-    cmd = "%s --version" % git_path
+    cmd = [git_path, "--version"]
     (rc, out, err) = module.run_command(cmd)
     if rc != 0:
         # one could fail_json here, but the version info is not that important,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/lib/ansible/release.py 
new/ansible_core-2.19.15/lib/ansible/release.py
--- old/ansible_core-2.19.14/lib/ansible/release.py     2026-10-05 
17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/lib/ansible/release.py     2026-11-02 
18:10:40.000000000 +0100
@@ -17,6 +17,6 @@
 
 from __future__ import annotations
 
-__version__ = '2.19.14'
+__version__ = '2.19.15'
 __author__ = 'Ansible, Inc.'
 __codename__ = "What Is and What Should Never Be"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ansible_core-2.19.14/pyproject.toml 
new/ansible_core-2.19.15/pyproject.toml
--- old/ansible_core-2.19.14/pyproject.toml     2026-10-05 17:06:28.000000000 
+0200
+++ new/ansible_core-2.19.15/pyproject.toml     2026-11-02 18:10:40.000000000 
+0100
@@ -1,5 +1,5 @@
 [build-system]
-requires = ["setuptools >= 66.1.0, <= 84.0.0", "wheel == 0.45.1"]  # lower 
bound to support controller Python versions, upper bound for latest version 
tested at release
+requires = ["setuptools >= 66.1.0, <= 84.2.1", "wheel == 0.45.1"]  # lower 
bound to support controller Python versions, upper bound for latest version 
tested at release
 build-backend = "setuptools.build_meta"
 
 [project]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/files/build_bad_tar.py
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/files/build_bad_tar.py
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/files/build_bad_tar.py
  2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/files/build_bad_tar.py
  2026-11-02 18:10:40.000000000 +0100
@@ -5,11 +5,11 @@
 
 from __future__ import annotations
 
+import argparse
 import hashlib
 import io
 import json
 import os
-import sys
 import tarfile
 from ansible.module_utils.common.file import S_IRWXU_RXG_RXO
 
@@ -44,9 +44,23 @@
 }
 
 
-def add_file(tar_file, filename, b_content, update_files=True):
+def calculate_target_filename(symlink_path, linkname):
+    """The target is relative to the symlink."""
+    symlink_dir = os.path.dirname(symlink_path)
+    if symlink_dir:
+        # tarfile will extract the linkname as {{ symlink_dir }}/{{ linkname 
}}, even if linkname is an absolute path
+        return "/".join([symlink_dir, linkname])
+    return linkname
+
+
+def add_file(tar_file, filename, b_content, update_files=True, 
symlink_linkname=None):
     tar_info = tarfile.TarInfo(filename)
-    tar_info.size = len(b_content)
+    if symlink_linkname is not None:
+        add_file(tar_file, calculate_target_filename(filename, 
symlink_linkname), b"", update_files=False)
+        tar_info.type = tarfile.SYMTYPE
+        tar_info.linkname = symlink_linkname
+    else:
+        tar_info.size = len(b_content)
     tar_info.mode = S_IRWXU_RXG_RXO
     tar_file.addfile(tarinfo=tar_info, fileobj=io.BytesIO(b_content))
 
@@ -58,14 +72,76 @@
             'name': filename,
             'ftype': 'file',
             'chksum_type': 'sha256',
-            'chksum_sha256': sha256.hexdigest(),
+            'chksum_sha256': sha256.hexdigest() if symlink_linkname is None 
else None,
             'format': 1
         })
 
 
-collection_tar = os.path.join(sys.argv[1], 'suspicious-test-1.0.0.tar.gz')
+def add_dir(tar_file, dir_name, symlink_linkname=None, update_files=True):
+    if symlink_linkname:
+        add_dir(tar_file, symlink_linkname, update_files=False)
+
+    tar_info = tarfile.TarInfo(dir_name)
+
+    if symlink_linkname is None:
+        tar_info.type = tarfile.DIRTYPE
+    else:
+        tar_info.type = tarfile.SYMTYPE
+        tar_info.linkname = symlink_linkname
+
+    tar_info.mode = 0o777
+    tar_file.addfile(tar_info)
+
+    if not update_files:
+        return
+
+    files['files'].append({
+        'name': dir_name,
+        'ftype': 'dir',
+        'chksum_type': 'sha256',
+        'chksum_sha256': None,
+        'format': 1,
+    })
+
+
+parser = argparse.ArgumentParser(description="Test suspiciously crafted 
collection artifacts.")
+parser.add_argument("dest", help="The destination directory for the collection 
artifact.")
+
+mutually_exclusive_group = parser.add_mutually_exclusive_group()
+mutually_exclusive_group.add_argument(
+    "--file", help="A file to add to the collection artifact.",
+)
+mutually_exclusive_group.add_argument(
+    "--dir", help="A directory to add to the collection artifact.",
+)
+mutually_exclusive_group.add_argument(
+    "--symlink-linkname", help="Add a symlink linkname to the collection 
artifact.",
+)
+parser.add_argument(
+    "--symlink", help="The name of the symlink to use with --symlink-linkname. 
Defaults to 'symlink'.",
+)
+
+
+args = parser.parse_args()
+
+collection_tar = os.path.join(args.dest, 'suspicious-test-1.0.0.tar.gz')
 with tarfile.open(collection_tar, mode='w:gz') as tar_file:
-    add_file(tar_file, '../../outside.sh', b"#!/usr/bin/env bash\necho \"you 
got pwned\"")
+    filename = args.file
+    dirname = args.dir
+
+    if args.symlink and not args.symlink_linkname:
+        parser.error("--symlink and --symlink-linkname must be used together")
+
+    if args.symlink_linkname:
+        if args.symlink_linkname.endswith(os.path.sep):
+            dirname = args.symlink or "symlink"
+        else:
+            filename = args.symlink or "symlink"
+
+    if dirname:
+        add_dir(tar_file, dirname, symlink_linkname=args.symlink_linkname)
+    elif filename:
+        add_file(tar_file, filename, b"#!/usr/bin/env bash\necho \"you got 
pwned\"", symlink_linkname=args.symlink_linkname)
 
     b_files = json.dumps(files).encode('utf-8')
     b_files_hash = hashlib.sha256()
@@ -73,12 +149,3 @@
     manifest['file_manifest_file']['chksum_sha256'] = b_files_hash.hexdigest()
     add_file(tar_file, 'FILES.json', b_files)
     add_file(tar_file, 'MANIFEST.json', json.dumps(manifest).encode('utf-8'))
-
-    b_manifest = json.dumps(manifest).encode('utf-8')
-
-    for name, b in [('MANIFEST.json', b_manifest), ('FILES.json', b_files)]:
-        b_io = io.BytesIO(b)
-        tar_info = tarfile.TarInfo(name)
-        tar_info.size = len(b)
-        tar_info.mode = 0o0644
-        tar_file.addfile(tarinfo=tar_info, fileobj=b_io)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/build_and_install_tarball.yml
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/build_and_install_tarball.yml
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/build_and_install_tarball.yml
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/build_and_install_tarball.yml
     2026-11-02 18:10:40.000000000 +0100
@@ -0,0 +1,37 @@
+- name: Test a specially built tarball
+  debug:
+    msg: "Creating tarball with arguments: {{ tarfile_arguments }}"
+
+- name: Create tarball
+  script: build_bad_tar.py {{ galaxy_dir | quote }} {{ tarfile_arguments }}
+
+- name: Try to install the tarball
+  command: ansible-galaxy collection install '{{ galaxy_dir 
}}/suspicious-test-1.0.0.tar.gz' {{ galaxy_verbosity }}
+  register: fail_bad_tar
+  ignore_errors: true
+  environment:
+    ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
+
+- name: Get the result of the install attempt
+  stat:
+    path: '{{ galaxy_dir }}/ansible_collections/suspicious'
+  register: fail_bad_tar_actual
+
+- name: Remove collection if it was installed
+  file:
+    path: '{{ galaxy_dir }}/ansible_collections'
+    state: absent
+  when: cleanup | default(True)
+
+- name: Assert the expected result
+  assert:
+    fail_msg: "{{ rc_msg }}{{ stderr_msg }}{{ stdout_msg }}"
+    that:
+      - fail_bad_tar.rc == expected_rc
+      - fail_bad_tar.stderr is search(expected_error)
+      - fail_bad_tar.stdout is search(expected_stdout)
+      - (expected_rc == 0) | ternary(fail_bad_tar_actual.stat.exists, not 
fail_bad_tar_actual.stat.exists)
+  vars:
+    rc_msg: "Expected rc: {{ expected_rc }}"
+    stderr_msg: "{{ (expected_error == '') | ternary('', ', error: ' ~ 
expected_error) }}"
+    stdout_msg: "{{ (expected_stdout == '') | ternary('', ', stdout: ' ~ 
expected_stdout) }}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
       2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/install.yml
       2026-11-02 18:10:40.000000000 +0100
@@ -285,26 +285,6 @@
         - "{{ galaxy_dir }}/scratch/tmp_parent/"
         - "{{ galaxy_dir }}/tmp_parent-name-1.0.0.tar.gz"
 
-- name: setup bad tarball - {{ test_id }}
-  script: build_bad_tar.py {{ galaxy_dir | quote }}
-
-- name: fail to install a collection from a bad tarball - {{ test_id }}
-  command: ansible-galaxy collection install '{{ galaxy_dir 
}}/suspicious-test-1.0.0.tar.gz' {{ galaxy_verbosity }}
-  register: fail_bad_tar
-  failed_when: fail_bad_tar.rc != 1 and "Cannot extract tar entry 
'../../outside.sh' as it will be placed outside the collection directory" not 
in fail_bad_tar.stderr
-  environment:
-    ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
-
-- name: get result of failed collection install - {{ test_id }}
-  stat:
-    path: '{{ galaxy_dir }}/ansible_collections\suspicious'
-  register: fail_bad_tar_actual
-
-- name: assert result of failed collection install - {{ test_id }}
-  assert:
-    that:
-    - not fail_bad_tar_actual.stat.exists
-
 - name: Find artifact url for namespace4.name
   uri:
     url: '{{ test_api_server 
}}v3/plugin/ansible/content/primary/collections/index/namespace4/name/versions/1.0.0/'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/install_tarball.yml
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/install_tarball.yml
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/install_tarball.yml
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/install_tarball.yml
       2026-11-02 18:10:40.000000000 +0100
@@ -0,0 +1,97 @@
+- name: Test unsafe tarball extraction
+  vars:
+    unsafe_rel_path: '../../outside'
+    unsafe_abs_path: '{{ galaxy_dir 
}}/ansible_collections/suspicious/test/../../outside'
+    safe_linkname: '{{ galaxy_dir 
}}/ansible_collections/suspicious/test/inside'
+    expected_rc: 1
+    expected_stdout: ""
+    tarfile_arguments: "{{ item }}"
+  block:
+    - name: Test unsafe file extraction
+      include_tasks: build_and_install_tarball.yml
+      loop:
+        - "--file '{{ unsafe_rel_path }}.sh'"
+        - "--file '{{ unsafe_abs_path }}.sh'"
+        - "--symlink '{{ unsafe_rel_path }}.sh' --symlink-linkname '{{ 
safe_linkname }}.sh'"
+        - "--symlink '{{ unsafe_abs_path }}.sh' --symlink-linkname '{{ 
safe_linkname }}.sh'"
+      vars:
+        expected_error: "Cannot extract tar entry"
+
+    - name: Test unsafe directory extraction
+      include_tasks: build_and_install_tarball.yml
+      loop:
+        - "--dir '{{ unsafe_rel_path }}'"
+        - "--dir '{{ unsafe_abs_path }}'"
+        - "--symlink '{{ unsafe_rel_path }}' --symlink-linkname '{{ 
safe_linkname }}/'"
+        - "--symlink '{{ unsafe_abs_path }}' --symlink-linkname '{{ 
safe_linkname }}/'"
+      vars:
+        expected_error: "Cannot extract directory"
+
+    - name: Test unsafe symlink linkname
+      include_tasks: build_and_install_tarball.yml
+      loop:
+        - "--symlink-linkname '{{ unsafe_rel_path }}.sh'"
+        - "--symlink-linkname '{{ unsafe_abs_path }}.sh'"
+        - "--symlink-linkname '{{ unsafe_rel_path }}/'"
+        - "--symlink-linkname '{{ unsafe_abs_path }}/'"
+        - "--symlink 'some_directory/symlink' --symlink-linkname 
'safe/../../../unsafe'"
+      vars:
+        expected_error: >-
+          Cannot extract symlink '.*symlink' in collection: path points to 
location outside of collection
+
+- name: Test safe tarball extraction
+  vars:
+    expected_rc: 0
+    expected_error: ""
+    expected_stdout: "suspicious\\.test:1\\.0\\.0 was installed successfully"
+    cleanup: False
+  block:
+    - name: Test successful directory extraction
+      include_tasks: build_and_install_tarball.yml
+      loop:
+        - "--dir 'safe/'"
+        - "--dir 'safe'"
+      loop_control:
+        loop_var: tarfile_arguments
+      vars:
+        cleanup: True
+
+    - name: Test successful relative linkname extraction
+      include_tasks: build_and_install_tarball.yml
+      vars:
+        tarfile_arguments: "--symlink 'some_directory/symlink' 
--symlink-linkname '../safe'"
+
+    - &stat_symlink
+      name: Check extracted the symlink exists
+      stat:
+        path: "{{ galaxy_dir 
}}/ansible_collections/suspicious/test/some_directory/symlink"
+      register: expected_symlink
+
+    - &realpath_symlink
+      name: Check extracted symlink is not broken
+      command: "realpath {{ galaxy_dir 
}}/ansible_collections/suspicious/test/some_directory/symlink"
+      ignore_errors: True
+      register: realpath_result
+
+    - &assert_symlink
+      assert:
+        that:
+          - expected_symlink.stat.exists
+          - realpath_result is not failed
+          - expected_symlink.stat.lnk_source == realpath_result.stdout == 
galaxy_dir ~ '/ansible_collections/suspicious/test/safe'
+
+    - &cleanup
+      name: Remove installed collection
+      file:
+        path: "{{ galaxy_dir }}/ansible_collections"
+        state: absent
+
+    - name: Test successful absolute linkname extraction
+      include_tasks: build_and_install_tarball.yml
+      vars:
+        tarfile_arguments: "--symlink some_directory/symlink 
--symlink-linkname '{{ galaxy_dir }}/ansible_collections/suspicious/test/safe'"
+
+    - <<: *stat_symlink
+    - <<: *realpath_symlink
+    - <<: *assert_symlink
+    - <<: *cleanup
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
  2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
  2026-11-02 18:10:40.000000000 +0100
@@ -63,6 +63,9 @@
       environment:
         ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
 
+- name: run ansible-galaxy collection tarball extraction tests
+  include_tasks: install_tarball.yml
+
 - name: run ansible-galaxy collection publish tests for {{ test_name }}
   include_tasks: publish.yml
   args:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-role/tasks/main.yml
 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-role/tasks/main.yml
--- 
old/ansible_core-2.19.14/test/integration/targets/ansible-galaxy-role/tasks/main.yml
        2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/integration/targets/ansible-galaxy-role/tasks/main.yml
        2026-11-02 18:10:40.000000000 +0100
@@ -63,11 +63,47 @@
   register: invalid
 
 - assert:
-    that: "invalid.rc != 0"
+    that:
+      - invalid.rc != 0
+      - 'invalid.stderr is search("Invalid linkname for tarfile member: path 
(:?/|/root/invalid) is not a subpath of the role")'
 
 - name: Uninstall invalid role
   command: ansible-galaxy role remove invalid-testrole
 
+- name: Test invalid role requirement name
+  vars:
+    abs_name: "{{ remote_tmp_dir }}/unsafe"
+    install_msg: "{{ abs_name }} was installed successfully"
+    external_msg: "The role name '{{ abs_name }}' resolves to a path outside 
of the configured role directory"
+  block:
+    - name: Create invalid requirements file
+      copy:
+        dest: invalid-requirements.yml
+        content: |-
+          - src: "{{ remote_tmp_dir }}/valid-role.tar"
+            name: "{{ abs_name }}"
+
+    - name: Test installing the role
+      command: ansible-galaxy install -r invalid-requirements.yml
+      register: fail_external
+      ignore_errors: True
+
+    - assert:
+        that:
+          - fail_external is failed
+          - fail_external.stderr is search(external_msg)
+          - fail_external.stdout is not search(install_msg)
+
+- name: Test --ignore-errors skips unsatisfiable invalid requirement name
+  command: ansible-galaxy install {{ remote_tmp_dir }}/roles/../valid-role.tar 
--roles-path {{ remote_tmp_dir }}/roles --ignore-errors
+  register: warn_external
+
+- assert:
+    that:
+      - warn_external is success
+      - warn_external.stderr is search("The role name '.*' resolves to a path 
outside of the configured role directory")
+      - warn_external.stdout is not search(".* was installed successfully")
+
 - import_tasks: dir-traversal.yml
 - import_tasks: valid-role-symlinks.yml
 - import_tasks: git-config-injection.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/lib/ansible_test/_data/completion/remote.txt 
new/ansible_core-2.19.15/test/lib/ansible_test/_data/completion/remote.txt
--- old/ansible_core-2.19.14/test/lib/ansible_test/_data/completion/remote.txt  
2026-10-05 17:06:28.000000000 +0200
+++ new/ansible_core-2.19.15/test/lib/ansible_test/_data/completion/remote.txt  
2026-11-02 18:10:40.000000000 +0100
@@ -2,7 +2,6 @@
 alpine become=doas_sudo provider=aws arch=x86_64
 fedora/41 python=3.13 become=sudo provider=aws arch=x86_64 alias=fedora/latest
 fedora become=sudo provider=aws arch=x86_64
-freebsd/13.5 python=3.11 python_dir=/usr/local/bin become=su_sudo provider=aws 
arch=x86_64 alias=freebsd/13
 freebsd/14.3 python=3.11 python_dir=/usr/local/bin become=su_sudo provider=aws 
arch=x86_64 alias=freebsd/14,freebsd/latest
 freebsd python_dir=/usr/local/bin become=su_sudo provider=aws arch=x86_64
 macos/15.3 python=3.13 python_dir=/usr/local/bin become=sudo provider=mac 
arch=aarch64 alias=macos/15,macos/latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/lib/ansible_test/_util/target/setup/bootstrap.sh 
new/ansible_core-2.19.15/test/lib/ansible_test/_util/target/setup/bootstrap.sh
--- 
old/ansible_core-2.19.14/test/lib/ansible_test/_util/target/setup/bootstrap.sh  
    2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/lib/ansible_test/_util/target/setup/bootstrap.sh  
    2026-11-02 18:10:40.000000000 +0100
@@ -187,9 +187,6 @@
         # Declare platform/python version combinations which do not have 
supporting OS packages available.
         # For these combinations ansible-test will use pip to install the 
requirements instead.
         case "${platform_version}/${python_version}" in
-            13.5/3.11)
-                # defaults available
-                ;;
             14.3/3.11)
                 # defaults available
                 ;;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ansible_core-2.19.14/test/units/cli/galaxy/test_collection_extract_tar.py 
new/ansible_core-2.19.15/test/units/cli/galaxy/test_collection_extract_tar.py
--- 
old/ansible_core-2.19.14/test/units/cli/galaxy/test_collection_extract_tar.py   
    2026-10-05 17:06:28.000000000 +0200
+++ 
new/ansible_core-2.19.15/test/units/cli/galaxy/test_collection_extract_tar.py   
    1970-01-01 01:00:00.000000000 +0100
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or 
https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import annotations
-
-import pytest
-
-from ansible.galaxy.collection import _extract_tar_dir
-
-
[email protected]
-def fake_tar_obj(mocker):
-    m_tarfile = mocker.Mock()
-    m_tarfile.type = mocker.Mock(return_value=b'99')
-    m_tarfile.SYMTYPE = mocker.Mock(return_value=b'22')
-
-    return m_tarfile
-
-
-def test_extract_tar_dir_exists(mocker, fake_tar_obj):
-    mocker.patch('os.makedirs', return_value=None)
-    m_makedir = mocker.patch('os.mkdir', return_value=None)
-    mocker.patch('os.path.isdir', return_value=True)
-
-    _extract_tar_dir(fake_tar_obj, '/some/dir', b'/some/dest')
-
-    assert not m_makedir.called
-
-
-def test_extract_tar_dir_does_not_exist(mocker, fake_tar_obj):
-    mocker.patch('os.makedirs', return_value=None)
-    m_makedir = mocker.patch('os.mkdir', return_value=None)
-    mocker.patch('os.path.isdir', return_value=False)
-
-    _extract_tar_dir(fake_tar_obj, '/some/dir', b'/some/dest')
-
-    assert m_makedir.called
-    assert m_makedir.call_args[0] == (b'/some/dir', 0o0755)

++++++ ansible_core-2.19.14.tar.gz.sha256 -> ansible_core-2.19.15.tar.gz.sha256 
++++++
--- 
/work/SRC/openSUSE:Factory/ansible-core-2.19/ansible_core-2.19.14.tar.gz.sha256 
    2026-10-08 13:28:31.235636416 +0200
+++ 
/work/SRC/openSUSE:Factory/.ansible-core-2.19.new.3759290/ansible_core-2.19.15.tar.gz.sha256
        2026-11-06 20:00:56.157626660 +0100
@@ -1 +1 @@
-1e7612788eaa6b3c87a3670ce86c64b830eba0ae2b3fcb25a772f276704163b4  
ansible_core-2.19.14.tar.gz
+05fa7f0730199b8e0dd9204f258075992143bd51dae71f68965b832a50d422fe  
ansible_core-2.19.15.tar.gz

Reply via email to