Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /app/services/lfs
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'app/services/lfs')
-rw-r--r--app/services/lfs/push_service.rb80
1 files changed, 80 insertions, 0 deletions
diff --git a/app/services/lfs/push_service.rb b/app/services/lfs/push_service.rb
new file mode 100644
index 00000000000..6e1a11ebff8
--- /dev/null
+++ b/app/services/lfs/push_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Lfs
+ # Lfs::PushService pushes the LFS objects associated with a project to a
+ # remote URL
+ class PushService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ # Match the canonical LFS client's batch size:
+ # https://github.com/git-lfs/git-lfs/blob/master/tq/transfer_queue.go#L19
+ BATCH_SIZE = 100
+
+ def execute
+ lfs_objects_relation.each_batch(of: BATCH_SIZE) do |objects|
+ push_objects(objects)
+ end
+
+ success
+ rescue => err
+ error(err.message)
+ end
+
+ private
+
+ # Currently we only set repository_type for design repository objects, so
+ # push mirroring must send objects with a `nil` repository type - but if the
+ # wiki repository uses LFS, its objects will also be sent. This will be
+ # addressed by https://gitlab.com/gitlab-org/gitlab/-/issues/250346
+ def lfs_objects_relation
+ project.lfs_objects_for_repository_types(nil, :project)
+ end
+
+ def push_objects(objects)
+ rsp = lfs_client.batch('upload', objects)
+ objects = objects.index_by(&:oid)
+
+ rsp.fetch('objects', []).each do |spec|
+ actions = spec['actions']
+ object = objects[spec['oid']]
+
+ upload_object!(object, spec) if actions&.key?('upload')
+ verify_object!(object, spec) if actions&.key?('verify')
+ end
+ end
+
+ def upload_object!(object, spec)
+ authenticated = spec['authenticated']
+ upload = spec.dig('actions', 'upload')
+
+ # The server wants us to upload the object but something is wrong
+ unless object && object.size == spec['size'].to_i
+ log_error("Couldn't match object #{spec['oid']}/#{spec['size']}")
+ return
+ end
+
+ lfs_client.upload(object, upload, authenticated: authenticated)
+ end
+
+ def verify_object!(object, spec)
+ # TODO: the remote has requested that we make another call to verify that
+ # the object has been sent correctly.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/250654
+ log_error("LFS upload verification requested, but not supported for #{object.oid}")
+ end
+
+ def url
+ params.fetch(:url)
+ end
+
+ def credentials
+ params.fetch(:credentials)
+ end
+
+ def lfs_client
+ strong_memoize(:lfs_client) do
+ Gitlab::Lfs::Client.new(url, credentials: credentials)
+ end
+ end
+ end
+end