sutty/app/models/site/repository.rb

124 lines
3.4 KiB
Ruby
Raw Normal View History

# 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
2019-08-09 19:49:25 +00:00
attr_reader :rugged, :changes, :path
def initialize(path)
2019-08-09 19:49:25 +00:00
@path = 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
#
2019-08-16 23:12:22 +00:00
def merge(usuarie)
merge = rugged.merge_commits(master, origin_master)
# 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?
commit = Rugged::Commit
2019-08-16 23:12:22 +00:00
.create(rugged, update_ref: 'HEAD',
parents: [master, origin_master],
tree: merge.write_tree(rugged),
message: I18n.t('sites.fetch.merge.message'),
author: author(usuarie), committer: committer)
# Forzamos el checkout para mover el HEAD al último commit y
# escribir los cambios
rugged.checkout 'HEAD', strategy: :force
commit
end
2019-08-16 23:12:22 +00:00
def master
rugged.branches['master'].target
end
def origin_master
rugged.branches['origin/master'].target
end
# 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
2019-07-30 21:07:08 +00:00
# Hay commits sin aplicar?
def needs_pull?
commits.empty?
end
2019-07-30 21:07:08 +00:00
# Guarda los cambios en git, de a un archivo por vez
2019-08-16 23:12:22 +00:00
def commit(file:, usuarie:, message:, remove: false)
remove ? rm(file) : add(file)
# Escribir los cambios para que el repositorio se vea tal cual
2019-07-30 21:07:08 +00:00
rugged.index.write
2019-08-16 23:12:22 +00:00
Rugged::Commit.create(rugged, message: message, update_ref: 'HEAD',
parents: [rugged.head.target],
tree: rugged.index.write_tree,
author: author(usuarie),
committer: committer)
2019-07-30 21:07:08 +00:00
end
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
2019-08-09 19:49:25 +00:00
2019-08-16 23:12:22 +00:00
def add(file)
rugged.index.add(relativize(file))
end
def rm(file)
rugged.index.remove(relativize(file))
end
2019-08-09 19:49:25 +00:00
private
def relativize(file)
Pathname.new(file).relative_path_from(Pathname.new(path)).to_s
end
end
end