6

I'm trying to retrieve a single file from by bitbucket branch instead of getting the entire branch using the git module. It's taking more than 2 minutes to get the entire branch and I really just need that one file.

4 Answers4

0

You can try git archive to get a file from remote git repository

git archive --remote=git://git.example.com/project.git HEAD:path/in/repo filename | tar -x

You can refer to the answer by Vonc for detailed information - For more info

Rajan Sharma
  • 2,211
  • 3
  • 21
  • 33
0

You can use sparse checkout option

git config core.sparseCheckout true
git remote add -f origin git:<<providde url>
echo "path/to/folder/*" > .git/info/sparse-checkout
git checkout <branchname>
Smily
  • 2,308
  • 2
  • 17
  • 41
0

Ansible's module git can do git archive but the problem is it does it from a local clone. If there is no local clone it clones first which is what you want to avoid so you cannot use module git.

Hence you have to use command or shell:

- name: Get a file using git archive
  command: git archive --remote=https://bitbucket.com/user/project.git HEAD:path/in/repo filename -o /path/to/archive.zip
phd
  • 82,685
  • 13
  • 120
  • 165
0

Ansible doesn't seem to support a sparse checkout. To do a sparse checkout with ansible, you can use the following code that i found here

---
- hosts: all
  
  vars:
    repo_url: ssh://git@github.com/user/repo.git
    base_dir: /var/www

    sparse_checkout:
      - path/to/archive.zip
  
  tasks:
    - name: prepare sparse git repository
      shell: |
        git init
        git config core.sparsecheckout true
        git remote add origin {{ repo_url }}
      args:
        chdir: "{{ base_dir }}"
        creates: "{{ base_dir }}/.git"

    - name: configure sparse-checkout
      copy:
        dest: "{{ base_dir }}/.git/info/sparse-checkout"
        content: '{{ sparse_checkout | join("\n") }}'

    - name: clone code
      shell: git pull origin master
      args:
        chdir: "{{ base_dir }}"
        creates: "{{ base_dir }}/{{ sparse_checkout | first }}"

You can adapt the folder to a single file as ive done above

If you want to just put all the code on your tasks file, you can use set_fact: "above" the previous code. example below

- name: set needed facts for ansible sparse checkout
  vars:
    git_user: '<git-token-name>'
    git_ansible_token: '<your-token>'
    ansible_repo_user: '<username>' #(this should probably already be configured in your main vars file, e.g. all.yml, or some group_vars, but if not, you can add it here)
  set_fact:
    # using gitlab as an example
    repo_url: 'https://{{ git_user }}:{{ git_ansible_token }}@gitlab.com/project/repo.git'
    base_dir: "~{{ ansible_repo_user }}/<your/path/to/desired/repo/folder>"
    # folders we want to reduce the repo to
    sparse_checkout:
      - path/to/archive.zip

Some additional code you may or may not need, is to create the base repo dir, because this checkout expects that it exists. so you would put this above the top git task that prepares the sparse checkout to create it first

- name: make parent repo dir for sparse checkout
  become: yes
  vars:
    ansible_become_user: '{{ ansible_repo_user }}'
  file:
    path: "{{ ansible_base_dir }}"
    state: directory
    mode: '0750'

So to pull all that together, including adding become to all the tasks, the entire thing could look like this on your tasks file;

- name: set needed facts for ansible sparse checkout
  vars:
    git_user: '<git-token-name>'
    git_ansible_token: '<your-token>'
    ansible_repo_user: '<username>' #(this should probably already be configured in your main vars file, e.g. all.yml, or some group_vars, but if not, you can add it here)
  set_fact:
    repo_url: 'https://{{ git_user }}:{{ git_ansible_token }}@gitlab.com/project/repo.git'
    base_dir: "~{{ ansible_repo_user }}/<your/path/to/desired/repo/folder>"
    # folders we want to reduce the repo to
    sparse_checkout:
      - path/to/archive.zip

- name: make parent repo dir for sparse checkout
  become: yes
  vars:
    ansible_become_user: '{{ ansible_repo_user }}'
  file:
    path: "{{ ansible_base_dir }}"
    state: directory
    mode: '0750'

- name: prepare sparse git repository
  become: yes
  vars:
    ansible_become_user: '{{ ansible_repo_user }}'
  shell: |
    git init
    git config core.sparsecheckout true
    git remote add origin {{ repo_url }}
  args:
    chdir: "{{ base_dir }}"
    creates: "{{ base_dir }}/.git"

- name: configure sparse-checkout
  become: yes
  vars:
    ansible_become_user: '{{ ansible_repo_user }}'
  copy:
  dest: "{{ base_dir }}/.git/info/sparse-checkout"
    content: '{{ sparse_checkout | join("\n") }}'

- name: clone code
  become: yes
  vars:
    ansible_become_user: '{{ ansible_repo_user }}'
  shell: git pull origin master
  args:
    chdir: "{{ base_dir }}"
    creates: "{{ base_dir }}/{{ sparse_checkout | first }}"

There was one other piece of additional functionality you could look into if its still not fast enough for you. I saw a way you can retreive a shorter history when you do your clone, so that you only bring in the last n commits. If i get time ill add that here.

Note, for the git project token, if your using gitlab, you create a project access token, for me i needed at least Role developer, and access RO for repo. If your using git, or another vcs, you will need to adapt accordingly.

Enjoy..

blamb
  • 4,220
  • 4
  • 32
  • 50