Skip to content

Commit

Permalink
Add new [lfs.server] and [lfs.client] config settings for batch sizes.
Browse files Browse the repository at this point in the history
This contains two backwards-compatible changes:
* in the lfs http_client, the number of lfs oids requested per batch is loaded from lfs.client#BATCH_SIZE and defaulted to the previous value of 20
* in the lfs server/service, the max number of lfs oids allowed in a batch api request is loaded from lfs.server#MAX_BATCH_SIZE and defaults to 'nil' which equates to the previous behavior of 'infinite'

This fixes #32306

Signed-off-by: Royce Remer <royceremer@gmail.com>
  • Loading branch information
rremer authored and Royce Remer committed Oct 24, 2024
1 parent 7cf611d commit 9de1d58
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
5 changes: 2 additions & 3 deletions modules/lfs/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/proxy"
"code.gitea.io/gitea/modules/setting"
)

const httpBatchSize = 20

// HTTPClient is used to communicate with the LFS server
// https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md
type HTTPClient struct {
Expand All @@ -30,7 +29,7 @@ type HTTPClient struct {

// BatchSize returns the preferred size of batchs to process
func (c *HTTPClient) BatchSize() int {
return httpBatchSize
return setting.LFSClient.BatchSize
}

func newHTTPClient(endpoint *url.URL, httpTransport *http.Transport) *HTTPClient {
Expand Down
35 changes: 28 additions & 7 deletions modules/setting/lfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import (
"code.gitea.io/gitea/modules/generate"
)

// LFS represents the configuration for Git LFS
const (
LFSConfigSectionLegacyServer = "server"
LFSConfigSectionServer = "lfs.server"
LFSConfigSectionClient = "lfs.client"
)

// LFS represents the legacy configuration for Git LFS, to be migrated to LFSServer
var LFS = struct {
StartServer bool `ini:"LFS_START_SERVER"`
AllowPureSSH bool `ini:"LFS_ALLOW_PURE_SSH"`
Expand All @@ -22,11 +28,22 @@ var LFS = struct {
Storage *Storage
}{}

// LFSServer represents configuration for hosting Git LFS
var LFSServer = struct {
MaxBatchSize int `ini:"MAX_BATCH_SIZE"`
}{}

// LFSClient represents configuration for mirroring upstream Git LFS
var LFSClient = struct {
BatchSize int `ini:"BATCH_SIZE"`
}{}

func loadLFSFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("server")
if err := sec.MapTo(&LFS); err != nil {
return fmt.Errorf("failed to map LFS settings: %v", err)
}
mustMapSetting(rootCfg, LFSConfigSectionServer, &LFSServer)
mustMapSetting(rootCfg, LFSConfigSectionClient, &LFSClient)
mustMapSetting(rootCfg, LFSConfigSectionLegacyServer, &LFS)

legacySec := rootCfg.Section(LFSConfigSectionLegacyServer)

lfsSec, _ := rootCfg.GetSection("lfs")

Expand All @@ -35,7 +52,7 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
// if these are removed, the warning will not be shown
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0")

if val := sec.Key("LFS_CONTENT_PATH").String(); val != "" {
if val := legacySec.Key("LFS_CONTENT_PATH").String(); val != "" {
if lfsSec == nil {
lfsSec = rootCfg.Section("lfs")
}
Expand All @@ -53,7 +70,11 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
LFS.LocksPagingNum = 50
}

LFS.HTTPAuthExpiry = sec.Key("LFS_HTTP_AUTH_EXPIRY").MustDuration(24 * time.Hour)
if LFSClient.BatchSize < 1 {
LFSClient.BatchSize = 20
}

LFS.HTTPAuthExpiry = legacySec.Key("LFS_HTTP_AUTH_EXPIRY").MustDuration(24 * time.Hour)

if !LFS.StartServer || !InstallLock {
return nil
Expand Down
16 changes: 16 additions & 0 deletions modules/setting/lfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,19 @@ STORAGE_TYPE = minio
assert.EqualValues(t, "gitea", LFS.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
}

func Test_LFSClientServerConfigs(t *testing.T) {
iniStr := `
[lfs.server]
MAX_BATCH_SIZE = 100
[lfs.client]
# will default to 20
BATCH_SIZE = 0
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)

assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, 100, LFSServer.MaxBatchSize)
assert.EqualValues(t, 20, LFSClient.BatchSize)
}
5 changes: 5 additions & 0 deletions services/lfs/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ func BatchHandler(ctx *context.Context) {
return
}

if setting.LFSServer.MaxBatchSize != 0 && len(br.Objects) > setting.LFSServer.MaxBatchSize {
writeStatus(ctx, http.StatusRequestEntityTooLarge)
return
}

contentStore := lfs_module.NewContentStore()

var responseObjects []*lfs_module.ObjectResponse
Expand Down

0 comments on commit 9de1d58

Please sign in to comment.