aboutsummaryrefslogtreecommitdiff
path: root/refstore/files/batch_apply.go
blob: 0c217c56d0c7bfe91c006354de873da809a3b29a (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package files

import (
	"errors"

	"codeberg.org/lindenii/furgit/refstore"
)

func (batch *Batch) Apply() ([]refstore.BatchResult, error) {
	if batch.closed {
		return nil, errors.New("refstore/files: batch already closed")
	}

	results := make([]refstore.BatchResult, len(batch.ops))
	seen := make(map[string]struct{}, len(batch.ops))

	for i, op := range batch.ops {
		results[i].Name = op.name

		if _, exists := seen[op.name]; exists {
			batch.closed = true

			err := errors.New("refstore/files: duplicate batch operation for " + `"` + op.name + `"`)
			for j := i; j < len(results); j++ {
				results[j].Name = batch.ops[j].name
				results[j].Error = err
			}

			return results, err
		}

		seen[op.name] = struct{}{}
	}

	for i, op := range batch.ops {
		tx := &Transaction{
			store: batch.store,
			ops:   []txOp{op},
		}

		err := tx.validateOp(op)
		if err != nil {
			results[i].Error = err

			continue
		}

		err = tx.Commit()
		if err == nil {
			continue
		}

		if isBatchRejected(err) {
			results[i].Error = err

			continue
		}

		batch.closed = true
		results[i].Error = err

		for j := i + 1; j < len(results); j++ {
			results[j].Name = batch.ops[j].name
			results[j].Error = err
		}

		return results, err
	}

	batch.closed = true

	return results, nil
}