From 960c8dcca450a27ab410833e6c5c35bcb9b8ccbf Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 14:50:36 -0300 Subject: [PATCH 1/5] feat: implementar un servicio liviano de git-lfs #9361 --- app/services/lfs_object_service.rb | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 app/services/lfs_object_service.rb diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb new file mode 100644 index 00000000..65db113d --- /dev/null +++ b/app/services/lfs_object_service.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +# Representa un objeto git LFS +class LfsObjectService + attr_reader :site, :blob, :usuarie + + # @param :site [Site] + # @param :blob [ActiveStorage::Blob] + def initialize(site:, blob:, usuarie:) + @site = site + @blob = blob + @usuarie = usuarie + end + + def process + # Crear el directorio + FileUtils.mkdir_p(File.dirname(object_path)) + + # Mover el archivo + FileUtils.mv(path, object_path) unless File.exist? object_path + + # Crear el pointer + Site::Writer.new(site: site, file: path, content: pointer).save + + # Commitear el pointer + site.repository.commit(file: path, usuarie: usuarie, message: File.basename(path)) + + # Eliminar el pointer + FileUtils.rm(path) + + # Hacer link duro del objeto al archivo + FileUtils.ln(object_path, path) + end + + # @return [String] + def path + @path ||= blob.service.path_for(blob.key) + end + + # @return [String] + def digest + @digest ||= Digest::SHA256.file(path).hexdigest + end + + # @return [String] + def object_path + @git_lfs_object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) + end + + # @return [Integer] + def size + @size ||= File.size(File.exist?(object_path) ? object_path : path) + end + + # @return [String] + def pointer + @pointer ||= + <<~POINTER + version https://git-lfs.github.com/spec/v1 + oid sha256:#{digest} + size #{size} + POINTER + end +end From 2215a00727d60d18147e76692dfe797a1183bd38 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:22:54 -0300 Subject: [PATCH 2/5] feat: commitear el archivo en lfs al subirlo --- app/lib/active_storage/service/jekyll_service.rb | 15 +++++++++------ app/services/lfs_object_service.rb | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 88ffa83c..6763ee0d 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -4,11 +4,6 @@ module ActiveStorage class Service # Sube los archivos a cada repositorio y los agrega al LFS de su # repositorio git. - # - # @todo: Implementar LFS. No nos gusta mucho la idea porque duplica - # el espacio en disco, pero es la única forma que tenemos (hasta que - # implementemos IPFS) para poder transferir los archivos junto con el - # sitio. class JekyllService < Service::DiskService # Genera un servicio para un sitio determinado # @@ -27,7 +22,10 @@ module ActiveStorage # @param :checksum [String] def upload(key, io, checksum: nil, **) instrument :upload, key: key, checksum: checksum do - IO.copy_stream(io, make_path_for(key)) unless exist?(key) + unless exist?(key) + IO.copy_stream(io, make_path_for(key)) + LfsObjectService.new(site: site, usuarie: current_usuarie, blob: blob).process + end ensure_integrity_of(key, checksum) if checksum end end @@ -91,6 +89,11 @@ module ActiveStorage def path_for(key) File.join root, folder_for(key), filename_for(key) end + + # @return [Site] + def site + @site ||= Site.find_by_name(File.basename(root)) + end end end end diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb index 65db113d..61775e12 100644 --- a/app/services/lfs_object_service.rb +++ b/app/services/lfs_object_service.rb @@ -44,7 +44,7 @@ class LfsObjectService # @return [String] def object_path - @git_lfs_object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) + @object_path ||= File.join(site.path, '.git', 'lfs', 'objects', digest[0..1], digest[2..3], digest) end # @return [Integer] From 2940b5d3e818d047afedf173df0d7a2d6b6f0613 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:29:49 -0300 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20no=20podemos=20saber=20qui=C3=A9n=20?= =?UTF-8?q?subi=C3=B3=20el=20archivo=20todav=C3=ADa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/active_storage/service/jekyll_service.rb | 2 +- app/services/lfs_object_service.rb | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index 6763ee0d..f399f440 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -24,7 +24,7 @@ module ActiveStorage instrument :upload, key: key, checksum: checksum do unless exist?(key) IO.copy_stream(io, make_path_for(key)) - LfsObjectService.new(site: site, usuarie: current_usuarie, blob: blob).process + LfsObjectService.new(site: site, blob: blob).process end ensure_integrity_of(key, checksum) if checksum end diff --git a/app/services/lfs_object_service.rb b/app/services/lfs_object_service.rb index 61775e12..bb62301d 100644 --- a/app/services/lfs_object_service.rb +++ b/app/services/lfs_object_service.rb @@ -2,14 +2,13 @@ # Representa un objeto git LFS class LfsObjectService - attr_reader :site, :blob, :usuarie + attr_reader :site, :blob # @param :site [Site] # @param :blob [ActiveStorage::Blob] - def initialize(site:, blob:, usuarie:) + def initialize(site:, blob:) @site = site @blob = blob - @usuarie = usuarie end def process @@ -23,7 +22,7 @@ class LfsObjectService Site::Writer.new(site: site, file: path, content: pointer).save # Commitear el pointer - site.repository.commit(file: path, usuarie: usuarie, message: File.basename(path)) + site.repository.commit(file: path, usuarie: author, message: File.basename(path)) # Eliminar el pointer FileUtils.rm(path) @@ -61,4 +60,8 @@ class LfsObjectService size #{size} POINTER end + + def author + @author ||= GitAuthor.new email: "disk_service@#{Site.domain}", name: 'DiskService' + end end From 2fb5bc24d5d21fdc2d32146ef114518ed96140c8 Mon Sep 17 00:00:00 2001 From: f Date: Sat, 25 Mar 2023 15:34:47 -0300 Subject: [PATCH 4/5] fix: encontrar el blob para este servicio --- app/lib/active_storage/service/jekyll_service.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/lib/active_storage/service/jekyll_service.rb b/app/lib/active_storage/service/jekyll_service.rb index f399f440..e6c5fda6 100644 --- a/app/lib/active_storage/service/jekyll_service.rb +++ b/app/lib/active_storage/service/jekyll_service.rb @@ -24,7 +24,7 @@ module ActiveStorage instrument :upload, key: key, checksum: checksum do unless exist?(key) IO.copy_stream(io, make_path_for(key)) - LfsObjectService.new(site: site, blob: blob).process + LfsObjectService.new(site: site, blob: blob_for(key)).process end ensure_integrity_of(key, checksum) if checksum end @@ -77,7 +77,7 @@ module ActiveStorage # @param :key [String] # @return [String] def filename_for(key) - ActiveStorage::Blob.where(key: key).limit(1).pluck(:filename).first.tap do |filename| + blob_for(key).filename.to_s.tap do |filename| raise ArgumentError, "Filename for key #{key} is blank" if filename.blank? end end @@ -92,7 +92,11 @@ module ActiveStorage # @return [Site] def site - @site ||= Site.find_by_name(File.basename(root)) + @site ||= Site.find_by_name(name) + end + + def blob_for(key) + ActiveStorage::Blob.find_by(key: key, service_name: name) end end end From ec47335f04ccc4b0a7424fcbe92ad65d7ce6c129 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 3 Apr 2023 12:44:09 -0300 Subject: [PATCH 5/5] fix: es necesario el arbol actual para ignorar cambios en paralelo cuando estamos guardando un post con archivos subidos y posts relacionados, al no usar el arbol actual se pisaban los archivos modificados y el repositorio quedaba en un estado inconsistente. --- app/models/site/repository.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/models/site/repository.rb b/app/models/site/repository.rb index f63288d4..62e4c45e 100644 --- a/app/models/site/repository.rb +++ b/app/models/site/repository.rb @@ -117,6 +117,9 @@ class Site def commit(file:, usuarie:, message:, remove: false) file = [file] unless file.respond_to? :each + # Cargar el árbol actual + rugged.index.read_tree rugged.head.target.tree + file.each do |f| remove ? rm(f) : add(f) end