Blog tech

Accéder à Git en Ruby avec la gem Rugged

Rédigé par Théo Delaune | 7 octobre 2014

Accéder à Git en Ruby peut-être utile au sein d’une application Rails. Rugged est une gem permettant l’accès à Git via libgit2. Nous allons explorer quelques unes de ses possibilités.

Libgit2 est une implémentation en C de Git. Cette librairie permet d’accéder à toutes les fonctions de Git grâce à son API.

Rugged permet de rendre toutes les fonctions de libgit2 accessibles directement en Ruby.

Chez Synbioz Rugged est utilisé au sein de PBTD. Nous l’utilisons au sein de l’application pour cloner, et mettre à jour les dépôts Git ajoutés à PBTD.

Nous avons également mis en place au sein de PBTD une librairie permettant d’accéder plus facilement à nos dépôts Git en utilisant toujours Rugged.

Pré-requis

Certaines librairies sont nécessaires au bon fonctionnement de Rugged:

  • CMake
  • pkg-config

Installons les :

(Mac OSX)

$ brew install cmake
$ brew install pkg-config

(Debian)

$ sudo apt-get install ruby-dev
$ sudo apt-get install cmake
$ sudo apt-get install pkg-config

Pour pouvoir récupérer des dépôts Git distants nous devons avoir ces librairies d’installées :

  • OpenSSL
  • LibSSH2
$ brew install openssl
$ brew install libssh2
$ sudo apt-get install openssl
$ sudo apt-get install libssh2-1
$ sudo apt-get install libssh2-1-dev

Installation de Rugged

Une fois toutes les dépendances installées nous allons pouvoir passer à l’installation de la gem en elle-même. Lors de l’installation de la gem, une version packagée de libgit2 fournie dans la gem sera elle aussi installée.

$ gem install rugged

Lors de l’utilisation de cette gem, si le message d’erreur suivant apparait:

Rugged::NetworkError: This transport isn't implemented. Sorry.

Il vous manque certainement une des librairies listées dans la partie Pré-requis.

Pratique

Avant de nous lancer dans son utilisation, nous allons configurer Rugged en y ajoutant l’accès à notre identité SSH.

Vérifiez que vous posséder un jeu de clés SSH valide et autorisé sur vos dépôt Git distants.

Si vous ne disposez pas de clés SSH voici comment en créer : Création clé SSH.

Utilisation avec l’agent ssh

Il faut tout d’abord ajouter votre identité ssh à l’agent ssh actuel :

$ ssh-add
credentials = Rugged::Credentials::SshKeyFromAgent.new(username: 'git')

username représente l’utilisateur ssh auquel nous allons nous connecter, prenons le cas de l’un de nos dépôts:

git@github.com:synbioz/pbtd.git

L’utilisateur se trouve avant le @ sur les adresses ssh, sur Github l’utilisateur est git.

Utilisation avec les clés ssh

Nous donnons directement à Rugged le chemin vers notre jeu de clés SSH.

credentials = Rugged::Credentials::SshKey.new(username: 'git', publickey: "/home/synbioz/.ssh/key.pub", privatekey: "/home/synbioz/.ssh/key")

Clonage d’un dépôt distant

repository_url = "git@github.com:synbioz/pbtd.git"
path = "pbtd"
@repository = Rugged::Repository.clone_at(repository_url, path, credentials: credentials)

repository_url contient l’url du dépôt distant path est le chemin où le dépôt va être cloné credentials sont les accès ssh que nous avons définis précédemment.

Commit de changements

Prenons le cas de l’ajout d’un fichier sur notre projet :

# 'DOCUMENTATION.md' est un fichier non versionné
# Nous voulons l'ajouter au dépôt

oid = Rugged::Blob.from_workdir @repository, "DOCUMENTATION.md"
index = @repository.index
index.read_tree(@repository.head.target.tree)
index.add(path: "DOCUMENTATION.md", oid: oid, mode: 33188)

# Auteur du commit
author = { email: "tdelaune@synbioz.com", name: "tdelaune@synbioz.com", time: Time.now }
# Ce commit aura un seul parent, le précédent commit
parents = [@repository.head.target.oid]
# ajout de notre fichier à l'arborescence git
tree = index.write_tree(@repository)

Rugged::Commit.create(@repository,
    :author => author,
    :message => "Ajout de DOCUMENTATION.md",
    :committer => author,
    :parents => parents,
    :tree => tree,
    :update_ref => "HEAD")

Push vers le dépôt distant

Pour ce faire nous devons récupérer le HEAD de notre dépôt local.

reference = @repository.head
remote = @repository.remotes['origin']

@repository.push(remote, [reference.name], {credentials: credentials})

Nous avons envoyé sur notre dépôt distant le HEAD de notre dépôt local, n’oubliez pas d’utiliser vos accès SSH.

Fetch du dépôt distant

remote = @repository.remotes['origin']
remote.fetch(credentials: credentials)

Pour ce faire nous allons avoir besoin d’accéder à l’adresse distante du dépôt qui est généralement origin. Il nous faut préciser à Rugged les informations SSH pour accéder au dépôt distant.

Changement de branche

@repository.checkout('my-branch')

Nous venons de passer sur la branche my-branch si elle existe.

Merge de branches

Nous voulons merger my-branch dans develop.

@repository.checkout("develop")

other_branch_commit = @repository.branches["my-branch"].target

@repository.references.update(@repository.head, other_branch_commit.oid)

Pull depuis votre dépôt distant

La commande git pull se décompose comme suit:

  • git fetch
  • git merge FETCH_HEAD

Il nous faut donc fetch et merge depuis notre dépôt distant :

@repository.checkout("develop")

# fetch
remote = @repository.remotes['origin']
remote.fetch(credentials: credentials)

# merge
distant_commit = @repository.branches["origin/develop"].target

@repository.references.update(@repository.head, distant_commit.oid)

Conclusion

Successeur de grit, Rugged se révèle indispensable pour utiliser Git simplement en Ruby. Mais la gem manque encore cruellement de documentation.

L’équipe Synbioz. Libres d’être ensemble.