ref: df1f2fb3daa1acd25c88510f259d5535fb482126
dir: /network/receivepack/service/apply.go/
package service
import (
"codeberg.org/lindenii/furgit/internal/utils"
refstore "codeberg.org/lindenii/furgit/ref/store"
)
func (service *Service) applyAtomic(result *Result, commands []Command) error {
total := len(commands)
utils.BestEffortFprintf(service.opts.Progress, "updating refs: 0/%d\r", total)
tx, err := service.opts.Refs.BeginTransaction()
if err != nil {
return err
}
for i, command := range commands {
err = queueWriteTransaction(tx, command)
if err != nil {
_ = tx.Abort()
fillCommandErrors(result, commands, err.Error())
utils.BestEffortFprintf(service.opts.Progress, "updating refs: failed at %d/%d.\n", i+1, total)
return nil
}
utils.BestEffortFprintf(service.opts.Progress, "updating refs: %d/%d\r", i+1, total)
}
err = tx.Commit()
if err != nil {
fillCommandErrors(result, commands, err.Error())
utils.BestEffortFprintf(service.opts.Progress, "updating refs: failed at commit.\n")
return nil
}
result.Applied = true
for _, command := range commands {
result.Commands = append(result.Commands, successCommandResult(command))
}
utils.BestEffortFprintf(service.opts.Progress, "updating refs: done.\n")
return nil
}
func (service *Service) applyBatch(result *Result, commands []Command) error {
total := len(commands)
utils.BestEffortFprintf(service.opts.Progress, "updating refs...\r")
batch, err := service.opts.Refs.BeginBatch()
if err != nil {
return err
}
for _, command := range commands {
err = queueWriteBatch(batch, command)
if err != nil {
_ = batch.Abort()
fillCommandErrors(result, commands, err.Error())
utils.BestEffortFprintf(service.opts.Progress, "updating refs: failed while queueing batch.\n")
return nil
}
}
batchResults, err := batch.Apply()
if err != nil && len(batchResults) == 0 {
utils.BestEffortFprintf(service.opts.Progress, "updating refs: failed at apply.\n")
return err
}
appliedAny := false
failedCount := 0
for i, command := range commands {
item := successCommandResult(command)
if i < len(batchResults) && batchResults[i].Error != nil {
item.Error = batchResults[i].Error.Error()
failedCount++
} else {
appliedAny = true
}
result.Commands = append(result.Commands, item)
utils.BestEffortFprintf(service.opts.Progress, "updating refs: %d/%d\r", i+1, total)
}
result.Applied = appliedAny
if failedCount == 0 {
utils.BestEffortFprintf(service.opts.Progress, "updating refs: done.\n")
} else {
utils.BestEffortFprintf(service.opts.Progress, "updating refs: failed (%d/%d).\n", failedCount, total)
}
return nil
}
func queueWriteTransaction(tx refstore.Transaction, command Command) error {
if isDelete(command) {
return tx.Delete(command.Name, command.OldID)
}
if command.OldID == command.OldID.Algorithm().Zero() {
return tx.Create(command.Name, command.NewID)
}
return tx.Update(command.Name, command.NewID, command.OldID)
}
func queueWriteBatch(batch refstore.Batch, command Command) error {
if isDelete(command) {
return batch.Delete(command.Name, command.OldID)
}
if command.OldID == command.OldID.Algorithm().Zero() {
return batch.Create(command.Name, command.NewID)
}
return batch.Update(command.Name, command.NewID, command.OldID)
}
func successCommandResult(command Command) CommandResult {
return CommandResult{
Name: command.Name,
RefName: command.Name,
OldID: new(command.OldID),
NewID: new(command.NewID),
}
}