diff --git a/app/models/site/config.rb b/app/models/site/config.rb index 34b64696..9660d9f1 100644 --- a/app/models/site/config.rb +++ b/app/models/site/config.rb @@ -19,33 +19,26 @@ class Site # Leer el archivo de configuración y setear los atributos en el # objeto actual, creando los metodos de ostruct def read - YAML.safe_load(File.read(path)).each do |key, value| + data = YAML.safe_load(File.read(path)) + @hash = data.hash + + data.each do |key, value| send("#{key}=".to_sym, value) end end # Escribe los cambios en el repositorio - # - # TODO: Convertir en una clase intermedia que también se encargue de - # guardar en git - def write - r = File.open(path, File::RDWR | File::CREAT, 0o640) do |f| - # Bloquear el archivo para que no sea accedido por otro - # proceso u otra editora - f.flock(File::LOCK_EX) + def write(usuarie) + return if persisted? - # Empezar por el principio - f.rewind + Site::Writer.new(site: site, file: path, + content: content.to_yaml, usuarie: usuarie, + message: I18n.t('sites.repository.config')).save + end - # Escribir el contenido en YAML - f.write(content.to_yaml) - - # Eliminar el resto - f.flush - f.truncate(f.pos) - end - - r.zero? + # Detecta si la configuración cambió comparando con el valor inicial + def persisted? + @hash == content.hash end # Obtener el contenido de la configuración como un hash, sin el diff --git a/app/models/site/repository.rb b/app/models/site/repository.rb index e182a2a9..f59ad217 100644 --- a/app/models/site/repository.rb +++ b/app/models/site/repository.rb @@ -78,5 +78,29 @@ class Site walker.each.to_a 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 diff --git a/app/models/site/writer.rb b/app/models/site/writer.rb new file mode 100644 index 00000000..f9350f12 --- /dev/null +++ b/app/models/site/writer.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +class Site + # Se encarga de guardar los cambios en los archivos y mantenerlos + # actualizados en git + class Writer + attr_reader :site, :file, :content, :usuarie, :message + + def initialize(site:, file:, content:, usuarie:, message:) + @site = site + @content = content + @file = file + @usuarie = usuarie + @message = message + end + + # rubocop:disable Metrics/AbcSize + def save + r = File.open(file, File::RDWR | File::CREAT, 0o640) do |f| + # Bloquear el archivo para que no sea accedido por otro + # proceso u otra editora + f.flock(File::LOCK_EX) + + # Empezar por el principio + f.rewind + + # Escribir el contenido + f.write(content) + + # Eliminar el resto + f.flush + f.truncate(f.pos) + end + + r.zero? && site.repository.commit(file: relative_file, + usuarie: usuarie, + message: message) + end + # rubocop:enable Metrics/AbcSize + + # Devuelve la ruta relativa a la raíz del sitio + def relative_file + Pathname.new(file).relative_path_from(Pathname.new(site.path)).to_s + end + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 157eaf62..9b03ef04 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -185,6 +185,8 @@ en: ejemplo: 'example' sites: + repository: + config: 'Changes in config' actions: 'Actions' posts: 'View and edit posts' title: 'Sites' diff --git a/config/locales/es.yml b/config/locales/es.yml index f2f43591..783933d7 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -194,6 +194,8 @@ es: También sirve para archivo histórico :) ejemplo: 'ejemplo' sites: + repository: + config: 'Cambios en la configuración' actions: 'Acciones' posts: 'Ver y editar artículos' title: 'Sitios' diff --git a/test/models/site/config_test.rb b/test/models/site/config_test.rb index 1ecbaba7..4ccaf370 100644 --- a/test/models/site/config_test.rb +++ b/test/models/site/config_test.rb @@ -23,12 +23,15 @@ class ConfigText < ActiveSupport::TestCase @site.config.lang = 'es' end - assert @site.config.write + assert @site.config.write(@usuarie) config = Site::Config.new(@site) assert_equal 'Test', config.name assert_equal 'es', config.lang + + assert_equal I18n.t('sites.repository.config'), + @site.repository.rugged.head.target.message end test 'se puede obtener información' do