# frozen_string_literal: true class Site # Acciones para el repositorio Git de un sitio. Por ahora hacemos un # uso muy básico de Git, con lo que asumimos varias cosas, por ejemplo # que un sitio tiene un solo origen, que siempre se trabaja con la # rama master, etc. class Repository attr_reader :rugged, :changes def initialize(path) @rugged = Rugged::Repository.new(path) @changes = 0 end def remote @remote ||= rugged.remotes.first end # Trae los cambios del repositorio de origen sin aplicarlos y # devuelve la cantidad de commits pendientes. # # XXX: Prestar atención a la velocidad de respuesta cuando tengamos # repositorios remotos. def fetch if remote.check_connection :fetch @changes = rugged.fetch(remote)[:received_objects] else 0 end end # Incorpora los cambios en el repositorio actual # # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/MethodLength def merge(author) master = rugged.branches['master'].target origin = rugged.branches['origin/master'].target merge = rugged.merge_commits(master, origin) # No hacemos nada si hay conflictos # # TODO: Enviar un correo a administración para poder revisar # manualmente. Idealmente no deberíamos tener conflictos pero # quién sabe. return if merge.conflicts? author = { name: author.name, email: author.email } commit = Rugged::Commit .create(rugged, parents: [master, origin], tree: merge.write_tree(rugged), message: I18n.t('sites.fetch.merge.message'), author: author, committer: author, update_ref: 'HEAD') # Forzamos el checkout para mover el HEAD al último commit y # escribir los cambios rugged.checkout 'HEAD', strategy: :force commit end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/MethodLength # Compara los commits entre el repositorio remoto y el actual para # que luego los podamos mostrar. def commits walker = Rugged::Walker.new rugged # Obtenemos todos los commits que existen en origin/master que no # están en la rama master local # # XXX: monitorear esto por performance walker.push 'refs/remotes/origin/master' walker.hide 'refs/heads/master' walker.each.to_a end # Hay commits sin aplicar? def needs_pull? commits.empty? end # Guarda los cambios en git, de a un archivo por vez # rubocop:disable Metrics/AbcSize def commit(file:, usuarie:, message:) rugged.index.add(file) rugged.index.write Rugged::Commit.create(rugged, update_ref: 'HEAD', parents: [rugged.head.target], tree: rugged.index.write_tree, message: message, author: author(usuarie), committer: committer) end # rubocop:enable Metrics/AbcSize def author(author) { name: author.name, email: author.email, time: Time.now } end def committer { name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now } end end end