Validate changes in a git repo for combined check and diff mode (#85110)

This commit validates changes in a shallow clone git repo and shows
a diff for combined check and diff mode in case if any old single
full commit sha is provided in version parameter instead of any
branch name or HEAD together with refspec parameter.
At present, if an old commit sha is provided to version parameter
for a shallow clone git repository initially cloned using depth: 1
and if ansible-playbook is executed with --diff --check together,
the command shows:
Failed to get proper diff between <before_sha> and <after_sha>
fatal: bad object <after_sha>
This commit is contained in:
Gaurav Pathak 2026-01-14 03:08:39 +05:30 committed by GitHub
parent fec9c3d50c
commit 6d383558c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 5 deletions

View file

@ -657,14 +657,14 @@ def reset(git_path, module, dest):
return module.run_command(cmd, check_rc=True, cwd=dest)
def get_diff(module, git_path, dest, repo, remote, depth, bare, before, after):
def get_diff(module, git_path, dest, repo, remote, depth, bare, before, after, refspec, force):
""" Return the difference between 2 versions """
if before is None:
return {'prepared': '>> Newly checked out %s' % after}
elif before != after:
# 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)
fetch(git_path, module, repo, dest, after, remote, depth, bare, refspec, git_version_used, force)
cmd = '%s diff %s %s' % (git_path, before, after)
(rc, out, err) = module.run_command(cmd, cwd=dest)
if rc == 0 and out:
@ -1317,7 +1317,7 @@ def main():
remote_head = get_remote_head(git_path, module, dest, version, repo, bare)
result.update(changed=True, after=remote_head)
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'], refspec, force)
if diff:
result['diff'] = diff
module.exit_json(**result)
@ -1366,7 +1366,7 @@ def main():
result.update(changed=(result['before'] != remote_head or remote_url_changed), after=remote_head)
# FIXME: This diff should fail since the new remote_head is not fetched yet?!
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'], refspec, force)
if diff:
result['diff'] = diff
module.exit_json(**result)
@ -1400,7 +1400,7 @@ def main():
if result['before'] != result['after'] or local_mods or submodules_updated or remote_url_changed:
result.update(changed=True)
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'], refspec, force)
if diff:
result['diff'] = diff

View file

@ -31,6 +31,7 @@
- import_tasks: missing_hostkey_acceptnew.yml
- import_tasks: no-destination.yml
- import_tasks: specific-revision.yml
- import_tasks: specific-rev-diff-check.yml
- import_tasks: submodules.yml
- import_tasks: change-repo-url.yml
- import_tasks: depth.yml

View file

@ -0,0 +1,49 @@
# Test that diff is displayed together with check mode in a shallow clone
# when checking out a specific revision
- name: SPECIFIC-REV-DIFF-CHECK | clear checkout_dir
file:
state: absent
path: '{{ checkout_dir }}'
- name: SPECIFIC-REVISION-DIFF-CHECK | shallow clone
git:
repo: "{{ repo_dir }}/shallow_branches/.git"
dest: "{{ checkout_dir }}/ansible-repo"
update: true
version: "main"
depth: 1
- name: SPECIFIC-REVISION-DIFF-CHECK | check mode with diff mode specific sha bad object
git:
repo: "{{ repo_dir }}/shallow_branches/.git"
dest: "{{ checkout_dir }}/ansible-repo"
depth: 1
update: true
version: '"{{ test_branch_ref_head_id }}"'
check_mode: true
diff: true
register: git_result
- assert:
that:
- "'>> Failed to get proper diff between' in git_result.diff.prepared"
- "'>> fatal: bad object' in git_result.diff.prepared"
- name: SPECIFIC-REVISION-DIFF-CHECK | check and diff mode with refspec force checkout old commit sha
git:
repo: "{{ repo_dir }}/shallow_branches/.git"
dest: "{{ checkout_dir }}/ansible-repo"
depth: 1
update: true
force: true
version: "{{ test_branch_ref_head_id }}"
refspec: "{{ test_branch_ref_head_id }}:refs/remotes/origin/devel"
check_mode: true
diff: true
register: git_result
- assert:
that:
- "'diff --git a' in git_result.diff.prepared"
- 'git_result.after == "{{ test_branch_ref_head_id }}"'