From 72bd10de9ba3c86f06bbcd0db0388b1f7cae0d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= Date: Mon, 9 Mar 2026 10:58:43 +0100 Subject: [PATCH 1/3] wip gitlab provider --- app/services/git/providers/gitlab.rb | 101 ++++++++++++++++++++------- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/app/services/git/providers/gitlab.rb b/app/services/git/providers/gitlab.rb index 5a0f0a921..fed4343c5 100644 --- a/app/services/git/providers/gitlab.rb +++ b/app/services/git/providers/gitlab.rb @@ -8,22 +8,41 @@ def url end def create_file(path, content) + new_path_file = tree_item_at_path(path) + action = new_path_file.nil? ? 'create' : 'update' + batch << { - action: 'create', + action: action, file_path: path, content: content } end def update_file(path, previous_path, content) - file = find previous_path - if file.present? && previous_path != path - batch << { - action: 'move', - file_path: path, - previous_path: previous_path - } + previous_path_file = tree_item_at_path(previous_path) + new_path_file = tree_item_at_path(path) + # En cas de dissonnance entre l'analyzer et le provider, on raise une erreur + if previous_path_file.nil? && new_path_file.nil? + raise "File to update does not exist on Git (repository: #{repository}, previous_path: #{previous_path}, path: #{path})" + end + + if previous_path_file.present? + if new_path_file.present? + # We will remove file at previous path and update the one at new path + batch << { + action: 'delete', + file_path: previous_path + } + else + # We will move file at previous path and update it at new path + batch << { + action: 'move', + file_path: path, + previous_path: previous_path + } + end end + batch << { action: 'update', file_path: path, @@ -32,11 +51,11 @@ def update_file(path, previous_path, content) end def destroy_file(path) - file = find path + file = tree_item_at_path(path) return if file.nil? batch << { action: 'delete', - file_path: path, + file_path: path } end @@ -53,28 +72,31 @@ def update_secrets(secrets) end def push(commit_message) + byebug return if !valid? || batch.empty? client.create_commit repository, branch, commit_message, batch + # The repo changed, invalidate the tree + @tree = nil + @tree_items_by_path = nil + # true end def computed_sha(string) - OpenSSL::Digest::SHA256.hexdigest string + # Git SHA-1 is calculated from the String "blob \x00" + # Source: https://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html + OpenSSL::Digest::SHA1.hexdigest "blob #{string.bytesize}\x00#{string}" end # https://gitlab.com/gitlab-org/gitlab/-/issues/23504 # TODO : Il faudrait, comme sur GitHub, stocker le tree pour éviter N requêtes pour N objets. def git_sha(path) - begin - file = find path - sha = file['content_sha256'] - rescue - sha = nil - end - sha + return if path.nil? + # Try to find in stored tree to avoid multiple queries + tree_item_at_path(path)&.dig(:sha) end def valid? @@ -89,22 +111,15 @@ def valid? end def branch - super.present? ? super - : 'main' + super.presence || 'main' end - # TODO def files_in_the_repository - super + @files_in_the_repository ||= tree.map { |file| file[:path] } end protected - def endpoint - @endpoint.blank? ? DEFAULT_ENDPOINT - : @endpoint - end - def client @client ||= Gitlab.client( endpoint: endpoint, @@ -112,6 +127,11 @@ def client ) end + def endpoint + @endpoint.blank? ? DEFAULT_ENDPOINT + : @endpoint + end + def find(path) client.get_file repository, path, @@ -120,4 +140,31 @@ def find(path) nil end + def tree_item_at_path(path) + tree_items_by_path[path] if tree_items_by_path.has_key? path + end + + def tree_items_by_path + unless @tree_items_by_path + @tree_items_by_path = {} + tree.each do |hash| + path = hash["path"] + @tree_items_by_path[path] = { + mode: hash["mode"], + type: hash["type"], + sha: hash["id"] + } + end + end + @tree_items_by_path + end + + def tree + @tree ||= client.tree(repository, { + ref: branch, + recursive: true, + per_page: 100 + }).auto_paginate + end + end From dc0039b4d64ecfc48587b7f4620d2963c26d05a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= Date: Mon, 23 Mar 2026 12:58:05 +0100 Subject: [PATCH 2/3] remove byebug --- app/services/git/providers/gitlab.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/services/git/providers/gitlab.rb b/app/services/git/providers/gitlab.rb index fed4343c5..958614816 100644 --- a/app/services/git/providers/gitlab.rb +++ b/app/services/git/providers/gitlab.rb @@ -72,7 +72,6 @@ def update_secrets(secrets) end def push(commit_message) - byebug return if !valid? || batch.empty? client.create_commit repository, branch, From 8871ed38d49c17cfdbc2e2bf7808c59ea2a3932f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= Date: Mon, 23 Mar 2026 14:38:56 +0100 Subject: [PATCH 3/3] fix update_file gitlab --- app/services/git/providers/gitlab.rb | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/app/services/git/providers/gitlab.rb b/app/services/git/providers/gitlab.rb index 958614816..61303c52f 100644 --- a/app/services/git/providers/gitlab.rb +++ b/app/services/git/providers/gitlab.rb @@ -26,25 +26,17 @@ def update_file(path, previous_path, content) raise "File to update does not exist on Git (repository: #{repository}, previous_path: #{previous_path}, path: #{path})" end - if previous_path_file.present? - if new_path_file.present? - # We will remove file at previous path and update the one at new path - batch << { - action: 'delete', - file_path: previous_path - } - else - # We will move file at previous path and update it at new path - batch << { - action: 'move', - file_path: path, - previous_path: previous_path - } - end + # We will remove file at previous path and create or update it at new path + if previous_path != path && previous_path_file.present? + batch << { + action: 'delete', + file_path: previous_path + } end + action = new_path_file.present? ? 'update' : 'create' batch << { - action: 'update', + action: action, file_path: path, content: content }