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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
package objectpool
import (
"bufio"
"context"
"fmt"
"gitlab.com/gitlab-org/gitaly/internal/command"
"gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/git/repository"
"gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
)
const (
sourceRemote = "origin"
sourceRefNamespace = "refs/remotes/" + sourceRemote
)
// FetchFromOrigin initializes the pool and fetches the objects from its origin repository
func (o *ObjectPool) FetchFromOrigin(ctx context.Context, origin *gitalypb.Repository) error {
if err := o.Init(ctx); err != nil {
return err
}
originPath, err := helper.GetPath(origin)
if err != nil {
return err
}
getRemotes, err := git.Command(ctx, o, "remote")
if err != nil {
return err
}
remoteReader := bufio.NewScanner(getRemotes)
var originExists bool
for remoteReader.Scan() {
if remoteReader.Text() == sourceRemote {
originExists = true
}
}
if err := getRemotes.Wait(); err != nil {
return err
}
var setOriginCmd *command.Command
if originExists {
setOriginCmd, err = git.Command(ctx, o, "remote", "set-url", sourceRemote, originPath)
if err != nil {
return err
}
} else {
setOriginCmd, err = git.Command(ctx, o, "remote", "add", sourceRemote, originPath)
if err != nil {
return err
}
}
if err := setOriginCmd.Wait(); err != nil {
return err
}
refSpec := fmt.Sprintf("+refs/*:%s/*", sourceRefNamespace)
fetchCmd, err := git.Command(ctx, o, "fetch", "--quiet", sourceRemote, refSpec)
if err != nil {
return err
}
if err := fetchCmd.Wait(); err != nil {
return err
}
packRefs, err := git.Command(ctx, o, "pack-refs", "--all")
if err != nil {
return err
}
if err := packRefs.Wait(); err != nil {
return err
}
return repackPool(ctx, o)
}
const danglingObjectNamespace = "refs/dangling"
func repackPool(ctx context.Context, pool repository.GitRepo) error {
globalOpts := []git.Option{
git.ValueFlag{"-c", "pack.island=" + sourceRefNamespace + "/heads"},
git.ValueFlag{"-c", "pack.island=" + sourceRefNamespace + "/tags"},
git.ValueFlag{"-c", "pack.writeBitmapHashCache=true"},
}
repackCmd, err := git.SafeCmd(ctx, pool, globalOpts, git.SubCmd{
Name: "repack",
Flags: []git.Option{
git.Flag{"-ad"},
git.Flag{"--keep-unreachable"}, // Prevent data loss
git.Flag{"--delta-islands"}, // Performance
git.Flag{"--write-bitmap-index"}, // Performance
},
})
if err != nil {
return err
}
if err := repackCmd.Wait(); err != nil {
return err
}
return nil
}
|