mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Detect separate git dir and set git config path value appropriately
PR #38016 Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
This commit is contained in:
parent
7d2012fdd7
commit
0a701ff746
3 changed files with 112 additions and 29 deletions
|
@ -597,6 +597,30 @@ def is_not_a_branch(git_path, module, dest):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_repo_path(dest, bare):
|
||||||
|
if bare:
|
||||||
|
repo_path = dest
|
||||||
|
else:
|
||||||
|
repo_path = os.path.join(dest, '.git')
|
||||||
|
# Check if the .git is a file. If it is a file, it means that the repository is in external directory respective to the working copy (e.g. we are in a
|
||||||
|
# submodule structure).
|
||||||
|
if os.path.isfile(repo_path):
|
||||||
|
with open(repo_path, 'r') as gitfile:
|
||||||
|
data = gitfile.read()
|
||||||
|
ref_prefix, gitdir = data.rstrip().split('gitdir: ', 1)
|
||||||
|
if ref_prefix:
|
||||||
|
raise ValueError('.git file has invalid git dir reference format')
|
||||||
|
|
||||||
|
# There is a possibility the .git file to have an absolute path.
|
||||||
|
if os.path.isabs(gitdir):
|
||||||
|
repo_path = gitdir
|
||||||
|
else:
|
||||||
|
repo_path = os.path.join(repo_path.split('.git')[0], gitdir)
|
||||||
|
if not os.path.isdir(repo_path):
|
||||||
|
raise ValueError('%s is not a directory' % repo_path)
|
||||||
|
return repo_path
|
||||||
|
|
||||||
|
|
||||||
def get_head_branch(git_path, module, dest, remote, bare=False):
|
def get_head_branch(git_path, module, dest, remote, bare=False):
|
||||||
'''
|
'''
|
||||||
Determine what branch HEAD is associated with. This is partly
|
Determine what branch HEAD is associated with. This is partly
|
||||||
|
@ -605,31 +629,16 @@ def get_head_branch(git_path, module, dest, remote, bare=False):
|
||||||
associated with. In the case of a detached HEAD, this will look
|
associated with. In the case of a detached HEAD, this will look
|
||||||
up the branch in .git/refs/remotes/<remote>/HEAD.
|
up the branch in .git/refs/remotes/<remote>/HEAD.
|
||||||
'''
|
'''
|
||||||
if bare:
|
|
||||||
repo_path = dest
|
|
||||||
else:
|
|
||||||
repo_path = os.path.join(dest, '.git')
|
|
||||||
# Check if the .git is a file. If it is a file, it means that we are in a submodule structure.
|
|
||||||
if os.path.isfile(repo_path):
|
|
||||||
try:
|
try:
|
||||||
git_conf = open(repo_path, 'rb')
|
repo_path = get_repo_path(dest, bare)
|
||||||
for line in git_conf:
|
except (IOError, ValueError) as err:
|
||||||
config_val = line.split(b(':'), 1)
|
|
||||||
if config_val[0].strip() == b('gitdir'):
|
|
||||||
gitdir = to_native(config_val[1].strip(), errors='surrogate_or_strict')
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# No repo path found
|
# No repo path found
|
||||||
return ''
|
"""``.git`` file does not have a valid format for detached Git dir."""
|
||||||
|
module.fail_json(
|
||||||
# There is a possibility the .git file to have an absolute path.
|
msg='Current repo does not have a valid reference to a '
|
||||||
if os.path.isabs(gitdir):
|
'separate Git dir or it refers to the invalid path',
|
||||||
repo_path = gitdir
|
details=str(err),
|
||||||
else:
|
)
|
||||||
repo_path = os.path.join(repo_path.split('.git')[0], gitdir)
|
|
||||||
except (IOError, AttributeError):
|
|
||||||
# No repo path found
|
|
||||||
return ''
|
|
||||||
# Read .git/HEAD for the name of the branch.
|
# Read .git/HEAD for the name of the branch.
|
||||||
# If we're in a detached HEAD state, look up the branch associated with
|
# If we're in a detached HEAD state, look up the branch associated with
|
||||||
# the remote HEAD in .git/refs/remotes/<remote>/HEAD
|
# the remote HEAD in .git/refs/remotes/<remote>/HEAD
|
||||||
|
@ -1019,10 +1028,17 @@ def main():
|
||||||
module.fail_json(msg="the destination directory must be specified unless clone=no")
|
module.fail_json(msg="the destination directory must be specified unless clone=no")
|
||||||
elif dest:
|
elif dest:
|
||||||
dest = os.path.abspath(dest)
|
dest = os.path.abspath(dest)
|
||||||
if bare:
|
try:
|
||||||
gitconfig = os.path.join(dest, 'config')
|
repo_path = get_repo_path(dest, bare)
|
||||||
else:
|
except (IOError, ValueError) as err:
|
||||||
gitconfig = os.path.join(dest, '.git', 'config')
|
# No repo path found
|
||||||
|
"""``.git`` file does not have a valid format for detached Git dir."""
|
||||||
|
module.fail_json(
|
||||||
|
msg='Current repo does not have a valid reference to a '
|
||||||
|
'separate Git dir or it refers to the invalid path',
|
||||||
|
details=str(err),
|
||||||
|
)
|
||||||
|
gitconfig = os.path.join(repo_path, 'config')
|
||||||
|
|
||||||
# create a wrapper script and export
|
# create a wrapper script and export
|
||||||
# GIT_SSH=<path> as an environment variable
|
# GIT_SSH=<path> as an environment variable
|
||||||
|
|
|
@ -36,3 +36,6 @@
|
||||||
- include_tasks: reset-origin.yml
|
- include_tasks: reset-origin.yml
|
||||||
- include_tasks: ambiguous-ref.yml
|
- include_tasks: ambiguous-ref.yml
|
||||||
- include_tasks: archive.yml
|
- include_tasks: archive.yml
|
||||||
|
- include_tasks: separate-git-dir.yml
|
||||||
|
when:
|
||||||
|
- git_version.stdout is version("1.7.5", '>=')
|
||||||
|
|
64
test/integration/targets/git/tasks/separate-git-dir.yml
Normal file
64
test/integration/targets/git/tasks/separate-git-dir.yml
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# test code for repositories with separate git dir updating
|
||||||
|
# see https://github.com/ansible/ansible/pull/38016
|
||||||
|
# see https://github.com/ansible/ansible/issues/30034
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | clear checkout_dir
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: '{{ checkout_dir }}'
|
||||||
|
|
||||||
|
- name: create a tempdir for separate git dir
|
||||||
|
local_action: shell mktemp -du
|
||||||
|
register: tempdir
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | clone with a separate git dir
|
||||||
|
command: git clone {{ repo_format1 }} {{ checkout_dir }} --separate-git-dir={{ tempdir.stdout }}
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | update repo the usual way
|
||||||
|
git:
|
||||||
|
repo: "{{ repo_format1 }}"
|
||||||
|
dest: "{{ checkout_dir }}"
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | set git dir to non-existent dir
|
||||||
|
shell: "echo gitdir: /dev/null/non-existent-dir > .git"
|
||||||
|
args:
|
||||||
|
chdir: "{{ checkout_dir }}"
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | update repo the usual way
|
||||||
|
git:
|
||||||
|
repo: "{{ repo_format1 }}"
|
||||||
|
dest: "{{ checkout_dir }}"
|
||||||
|
ignore_errors: yes
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | check update has failed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | set .git file to bad format
|
||||||
|
shell: "echo some text gitdir: {{ checkout_dir }} > .git"
|
||||||
|
args:
|
||||||
|
chdir: "{{ checkout_dir }}"
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | update repo the usual way
|
||||||
|
git:
|
||||||
|
repo: "{{ repo_format1 }}"
|
||||||
|
dest: "{{ checkout_dir }}"
|
||||||
|
ignore_errors: yes
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | check update has failed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | clear separate git dir
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: "{{ tempdir.stdout }}"
|
||||||
|
|
||||||
|
- name: SEPARATE-GIT-DIR | clear checkout_dir
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: '{{ checkout_dir }}'
|
Loading…
Reference in a new issue