Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 5d3dc69

Browse files
committed
config: support pack.window
1 parent 7eafff9 commit 5d3dc69

File tree

10 files changed

+74
-33
lines changed

10 files changed

+74
-33
lines changed

config/config.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"sort"
9+
"strconv"
910

1011
format "gopkg.in/src-d/go-git.v4/plumbing/format/config"
1112
)
@@ -40,6 +41,14 @@ type Config struct {
4041
// Worktree is the path to the root of the working tree.
4142
Worktree string
4243
}
44+
45+
Pack struct {
46+
// Window controls the size of the sliding window for delta
47+
// compression. The default is 10. A value of 0 turns off
48+
// delta compression entirely.
49+
Window uint
50+
}
51+
4352
// Remotes list of repository remotes, the key of the map is the name
4453
// of the remote, should equal to RemoteConfig.Name.
4554
Remotes map[string]*RemoteConfig
@@ -81,10 +90,14 @@ const (
8190
remoteSection = "remote"
8291
submoduleSection = "submodule"
8392
coreSection = "core"
93+
packSection = "pack"
8494
fetchKey = "fetch"
8595
urlKey = "url"
8696
bareKey = "bare"
8797
worktreeKey = "worktree"
98+
windowKey = "window"
99+
100+
defaultPackWindow = uint(10)
88101
)
89102

90103
// Unmarshal parses a git-config file and stores it.
@@ -98,6 +111,9 @@ func (c *Config) Unmarshal(b []byte) error {
98111
}
99112

100113
c.unmarshalCore()
114+
if err := c.unmarshalPack(); err != nil {
115+
return err
116+
}
101117
c.unmarshalSubmodules()
102118
return c.unmarshalRemotes()
103119
}
@@ -111,6 +127,21 @@ func (c *Config) unmarshalCore() {
111127
c.Core.Worktree = s.Options.Get(worktreeKey)
112128
}
113129

130+
func (c *Config) unmarshalPack() error {
131+
s := c.Raw.Section(packSection)
132+
window := s.Options.Get(windowKey)
133+
if window == "" {
134+
c.Pack.Window = defaultPackWindow
135+
} else {
136+
winUint, err := strconv.ParseUint(window, 10, 32)
137+
if err != nil {
138+
return err
139+
}
140+
c.Pack.Window = uint(winUint)
141+
}
142+
return nil
143+
}
144+
114145
func (c *Config) unmarshalRemotes() error {
115146
s := c.Raw.Section(remoteSection)
116147
for _, sub := range s.Subsections {
@@ -138,6 +169,7 @@ func (c *Config) unmarshalSubmodules() {
138169
// Marshal returns Config encoded as a git-config file.
139170
func (c *Config) Marshal() ([]byte, error) {
140171
c.marshalCore()
172+
c.marshalPack()
141173
c.marshalRemotes()
142174
c.marshalSubmodules()
143175

@@ -158,6 +190,13 @@ func (c *Config) marshalCore() {
158190
}
159191
}
160192

193+
func (c *Config) marshalPack() {
194+
s := c.Raw.Section(packSection)
195+
if c.Pack.Window != defaultPackWindow {
196+
s.SetOption(windowKey, fmt.Sprintf("%d", c.Pack.Window))
197+
}
198+
}
199+
161200
func (c *Config) marshalRemotes() {
162201
s := c.Raw.Section(remoteSection)
163202
newSubsections := make(format.Subsections, 0, len(c.Remotes))

config/config_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ func (s *ConfigSuite) TestUnmarshall(c *C) {
1010
input := []byte(`[core]
1111
bare = true
1212
worktree = foo
13+
[pack]
14+
window = 20
1315
[remote "origin"]
1416
url = [email protected]:mcuadros/go-git.git
1517
fetch = +refs/heads/*:refs/remotes/origin/*
@@ -33,6 +35,7 @@ func (s *ConfigSuite) TestUnmarshall(c *C) {
3335

3436
c.Assert(cfg.Core.IsBare, Equals, true)
3537
c.Assert(cfg.Core.Worktree, Equals, "foo")
38+
c.Assert(cfg.Pack.Window, Equals, uint(20))
3639
c.Assert(cfg.Remotes, HasLen, 2)
3740
c.Assert(cfg.Remotes["origin"].Name, Equals, "origin")
3841
c.Assert(cfg.Remotes["origin"].URLs, DeepEquals, []string{"[email protected]:mcuadros/go-git.git"})
@@ -51,6 +54,8 @@ func (s *ConfigSuite) TestMarshall(c *C) {
5154
output := []byte(`[core]
5255
bare = true
5356
worktree = bar
57+
[pack]
58+
window = 20
5459
[remote "alt"]
5560
url = [email protected]:mcuadros/go-git.git
5661
url = [email protected]:src-d/go-git.git
@@ -65,6 +70,7 @@ func (s *ConfigSuite) TestMarshall(c *C) {
6570
cfg := NewConfig()
6671
cfg.Core.IsBare = true
6772
cfg.Core.Worktree = "bar"
73+
cfg.Pack.Window = 20
6874
cfg.Remotes["origin"] = &RemoteConfig{
6975
Name: "origin",
7076
URLs: []string{"[email protected]:mcuadros/go-git.git"},
@@ -92,6 +98,8 @@ func (s *ConfigSuite) TestUnmarshallMarshall(c *C) {
9298
bare = true
9399
worktree = foo
94100
custom = ignored
101+
[pack]
102+
window = 20
95103
[remote "origin"]
96104
url = [email protected]:mcuadros/go-git.git
97105
fetch = +refs/heads/*:refs/remotes/origin/*

options.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,8 @@ type PushOptions struct {
175175
Auth transport.AuthMethod
176176
// Progress is where the human readable information sent by the server is
177177
// stored, if nil nothing is stored.
178-
Progress sideband.Progress
179-
// SkipCompression can be true if the caller doesn't need
180-
// delta-compressed objects pushed to the remote. This can be useful to
181-
// avoid CPU overhead when the objects don't need to be
182-
// transferred across a network. If the remote wants a compressed
183-
// repo after the transfer, it can run `git gc --aggressive` or
184-
// `git repack -a -d -f --depth=250 --window=250` as needed.
185-
SkipCompression bool
186-
StatusChan plumbing.StatusChan
178+
Progress sideband.Progress
179+
StatusChan plumbing.StatusChan
187180
}
188181

189182
// Validate validates the fields and sets the default values.

plumbing/format/packfile/delta_selector.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ import (
99
)
1010

1111
const (
12-
// How far back in the sorted list to search for deltas. 10 is
13-
// the default in command line git.
14-
deltaWindowSize = 10
1512
// deltas based on deltas, how many steps we can do.
1613
// 50 is the default value used in JGit
1714
maxDepth = int64(50)
@@ -35,7 +32,7 @@ func newDeltaSelector(s storer.EncodedObjectStorer) *deltaSelector {
3532
// creating deltas if it's suitable, using an specific internal logic
3633
func (dw *deltaSelector) ObjectsToPack(
3734
hashes []plumbing.Hash,
38-
skipCompression bool,
35+
packWindow uint,
3936
statusChan plumbing.StatusChan,
4037
) ([]*ObjectToPack, error) {
4138
update := plumbing.StatusUpdate{
@@ -44,12 +41,12 @@ func (dw *deltaSelector) ObjectsToPack(
4441
}
4542
statusChan.SendUpdate(update)
4643

47-
otp, err := dw.objectsToPack(hashes, skipCompression, statusChan, update)
44+
otp, err := dw.objectsToPack(hashes, packWindow, statusChan, update)
4845
if err != nil {
4946
return nil, err
5047
}
5148

52-
if skipCompression {
49+
if packWindow == 0 {
5350
return otp, nil
5451
}
5552

@@ -87,7 +84,7 @@ func (dw *deltaSelector) ObjectsToPack(
8784
objs := objs
8885
wg.Add(1)
8986
go func() {
90-
if walkErr := dw.walk(objs, statusChan, &update, &updateMutex); walkErr != nil {
87+
if walkErr := dw.walk(objs, packWindow, statusChan, &update, &updateMutex); walkErr != nil {
9188
once.Do(func() {
9289
err = walkErr
9390
})
@@ -106,15 +103,15 @@ func (dw *deltaSelector) ObjectsToPack(
106103

107104
func (dw *deltaSelector) objectsToPack(
108105
hashes []plumbing.Hash,
109-
skipCompression bool,
106+
packWindow uint,
110107
statusChan plumbing.StatusChan,
111108
update plumbing.StatusUpdate,
112109
) ([]*ObjectToPack, error) {
113110
var objectsToPack []*ObjectToPack
114111
for _, h := range hashes {
115112
var o plumbing.EncodedObject
116113
var err error
117-
if skipCompression {
114+
if packWindow == 0 {
118115
o, err = dw.encodedObject(h)
119116
} else {
120117
o, err = dw.encodedDeltaObject(h)
@@ -134,7 +131,7 @@ func (dw *deltaSelector) objectsToPack(
134131
statusChan.SendUpdateIfPossible(update)
135132
}
136133

137-
if skipCompression {
134+
if packWindow == 0 {
138135
return objectsToPack, nil
139136
}
140137

@@ -259,6 +256,7 @@ func (dw *deltaSelector) sort(objectsToPack []*ObjectToPack) {
259256

260257
func (dw *deltaSelector) walk(
261258
objectsToPack []*ObjectToPack,
259+
packWindow uint,
262260
statusChan plumbing.StatusChan,
263261
update *plumbing.StatusUpdate,
264262
updateMutex *sync.Mutex,
@@ -288,7 +286,7 @@ func (dw *deltaSelector) walk(
288286
continue
289287
}
290288

291-
for j := i - 1; j >= 0 && i-j < deltaWindowSize; j-- {
289+
for j := i - 1; j >= 0 && i-j < int(packWindow); j-- {
292290
base := objectsToPack[j]
293291
// Objects must use only the same type as their delta base.
294292
// Since objectsToPack is sorted by type and size, once we find

plumbing/format/packfile/encoder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ func NewEncoder(w io.Writer, s storer.EncodedObjectStorer, useRefDeltas bool) *E
4949
// and writes it to the writer in the Encoder.
5050
func (e *Encoder) Encode(
5151
hashes []plumbing.Hash,
52-
skipCompression bool,
52+
packWindow uint,
5353
statusChan plumbing.StatusChan,
5454
) (plumbing.Hash, error) {
5555
objects, err := e.selector.ObjectsToPack(
56-
hashes, skipCompression, statusChan)
56+
hashes, packWindow, statusChan)
5757
if err != nil {
5858
return plumbing.ZeroHash, err
5959
}

plumbing/transport/server/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ func (s *upSession) UploadPack(ctx context.Context, req *packp.UploadPackRequest
165165
pr, pw := io.Pipe()
166166
e := packfile.NewEncoder(pw, s.storer, false)
167167
go func() {
168-
_, err := e.Encode(objs, false, nil)
168+
// TODO: plumb through a pack window.
169+
_, err := e.Encode(objs, 10, nil)
169170
pw.CloseWithError(err)
170171
}()
171172

plumbing/transport/test/receive_pack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ func (s *ReceivePackSuite) testSendPackDeleteReference(c *C) {
348348
func (s *ReceivePackSuite) emptyPackfile() io.ReadCloser {
349349
var buf bytes.Buffer
350350
e := packfile.NewEncoder(&buf, memory.NewStorage(), false)
351-
_, err := e.Encode(nil, false, nil)
351+
_, err := e.Encode(nil, 10, nil)
352352
if err != nil {
353353
panic(err)
354354
}

plumbing/transport/test/upload_pack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func (s *UploadPackSuite) checkObjectNumber(c *C, r io.Reader, n int) {
262262
storage := memory.NewStorage()
263263
d, err := packfile.NewDecoder(scanner, storage)
264264
c.Assert(err, IsNil)
265-
_, err = d.Decode()
265+
_, err = d.Decode(nil)
266266
c.Assert(err, IsNil)
267267
c.Assert(len(storage.Objects), Equals, n)
268268
}

remote.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
149149
}
150150
}
151151

152-
rs, err := pushHashes(
153-
ctx, s, r.s, req, hashesToPush, o.SkipCompression, o.StatusChan)
152+
rs, err := pushHashes(ctx, s, r.s, req, hashesToPush, o.StatusChan)
154153
if err != nil {
155154
return err
156155
}
@@ -814,19 +813,22 @@ func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) {
814813
func pushHashes(
815814
ctx context.Context,
816815
sess transport.ReceivePackSession,
817-
sto storer.EncodedObjectStorer,
816+
s storage.Storer,
818817
req *packp.ReferenceUpdateRequest,
819818
hs []plumbing.Hash,
820-
skipCompression bool,
821819
statusChan plumbing.StatusChan,
822820
) (*packp.ReportStatus, error) {
823821

824822
rd, wr := io.Pipe()
825823
req.Packfile = rd
824+
config, err := s.Config()
825+
if err != nil {
826+
return nil, err
827+
}
826828
done := make(chan error)
827829
go func() {
828-
e := packfile.NewEncoder(wr, sto, false)
829-
if _, err := e.Encode(hs, skipCompression, statusChan); err != nil {
830+
e := packfile.NewEncoder(wr, s, false)
831+
if _, err := e.Encode(hs, config.Pack.Window, statusChan); err != nil {
830832
done <- wr.CloseWithError(err)
831833
return
832834
}

storage/test/storage_suite.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (s *BaseStorageSuite) TestPackfileWriter(c *C) {
158158
c.Skip("not a storer.PackWriter")
159159
}
160160

161-
pw, err := pwr.PackfileWriter()
161+
pw, err := pwr.PackfileWriter(nil)
162162
c.Assert(err, IsNil)
163163

164164
f := fixtures.Basic().One()
@@ -414,7 +414,7 @@ func (s *BaseStorageSuite) TestDeltaObjectStorer(c *C) {
414414
c.Skip("not a storer.PackWriter")
415415
}
416416

417-
pw, err := pwr.PackfileWriter()
417+
pw, err := pwr.PackfileWriter(nil)
418418
c.Assert(err, IsNil)
419419

420420
f := fixtures.Basic().One()

0 commit comments

Comments
 (0)