1package git
2
3import (
4 "errors"
5 "time"
6
7 "github.com/go-git/go-git/v5/plumbing"
8 "github.com/go-git/go-git/v5/plumbing/storer"
9)
10
11type PruneHandler func(unreferencedObjectHash plumbing.Hash) error
12type PruneOptions struct {
13 // OnlyObjectsOlderThan if set to non-zero value
14 // selects only objects older than the time provided.
15 OnlyObjectsOlderThan time.Time
16 // Handler is called on matching objects
17 Handler PruneHandler
18}
19
20var ErrLooseObjectsNotSupported = errors.New("loose objects not supported")
21
22// DeleteObject deletes an object from a repository.
23// The type conveniently matches PruneHandler.
24func (r *Repository) DeleteObject(hash plumbing.Hash) error {
25 los, ok := r.Storer.(storer.LooseObjectStorer)
26 if !ok {
27 return ErrLooseObjectsNotSupported
28 }
29
30 return los.DeleteLooseObject(hash)
31}
32
33func (r *Repository) Prune(opt PruneOptions) error {
34 los, ok := r.Storer.(storer.LooseObjectStorer)
35 if !ok {
36 return ErrLooseObjectsNotSupported
37 }
38
39 pw := newObjectWalker(r.Storer)
40 err := pw.walkAllRefs()
41 if err != nil {
42 return err
43 }
44 // Now walk all (loose) objects in storage.
45 return los.ForEachObjectHash(func(hash plumbing.Hash) error {
46 // Get out if we have seen this object.
47 if pw.isSeen(hash) {
48 return nil
49 }
50 // Otherwise it is a candidate for pruning.
51 // Check out for too new objects next.
52 if !opt.OnlyObjectsOlderThan.IsZero() {
53 // Errors here are non-fatal. The object may be e.g. packed.
54 // Or concurrently deleted. Skip such objects.
55 t, err := los.LooseObjectTime(hash)
56 if err != nil {
57 return nil
58 }
59 // Skip too new objects.
60 if !t.Before(opt.OnlyObjectsOlderThan) {
61 return nil
62 }
63 }
64 return opt.Handler(hash)
65 })
66}