Skip to content

Commit e1ed0cf

Browse files
committed
Implement reference pruning for pulls.
1 parent 787446c commit e1ed0cf

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

internal/pull/pull.go

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"os"
1111
"regexp"
12+
"strings"
1213

1314
log "github.com/sirupsen/logrus"
1415

@@ -90,16 +91,51 @@ func (pullService *pullService) pullGit(fresh bool) error {
9091
}
9192
}
9293

94+
refSpecs := []config.RefSpec{
95+
config.RefSpec("+refs/heads/*:" + cachedirectory.CacheReferencePrefix + "heads/*"),
96+
config.RefSpec("+refs/tags/*:" + cachedirectory.CacheReferencePrefix + "tags/*"),
97+
}
98+
reverseRefSpecs := []config.RefSpec{}
99+
for _, refSpec := range refSpecs {
100+
reverseRefSpecs = append(reverseRefSpecs, refSpec.Reverse())
101+
}
102+
103+
remote, err := localRepository.Remote(git.DefaultRemoteName)
104+
if err != nil {
105+
return errors.Wrap(err, "Error getting remote.")
106+
}
107+
remoteReferences, err := remote.List(&git.ListOptions{Auth: credentials})
108+
if err != nil {
109+
return errors.Wrap(err, "Error listing remote references.")
110+
}
111+
localReferences, err := localRepository.References()
112+
if err != nil {
113+
return errors.Wrap(err, "Error listing local references.")
114+
}
115+
localReferences.ForEach(func(localReference *plumbing.Reference) error {
116+
if !strings.HasPrefix(localReference.Name().String(), "refs/") {
117+
return nil
118+
}
119+
for _, remoteReference := range remoteReferences {
120+
remoteReferenceName := strings.TrimPrefix(remoteReference.Name().String(), "refs/")
121+
if cachedirectory.CacheReferencePrefix+remoteReferenceName == localReference.Name().String() {
122+
return nil
123+
}
124+
}
125+
err := localRepository.Storer.RemoveReference(localReference.Name())
126+
if err != nil {
127+
return errors.Wrap(err, "Error pruning reference.")
128+
}
129+
return nil
130+
})
131+
93132
err = localRepository.FetchContext(pullService.ctx, &git.FetchOptions{
94133
RemoteName: git.DefaultRemoteName,
95-
RefSpecs: []config.RefSpec{
96-
config.RefSpec("+refs/heads/*:" + cachedirectory.CacheReferencePrefix + "heads/*"),
97-
config.RefSpec("+refs/tags/*:" + cachedirectory.CacheReferencePrefix + "tags/*"),
98-
},
99-
Progress: os.Stderr,
100-
Tags: git.NoTags,
101-
Force: true,
102-
Auth: credentials,
134+
RefSpecs: refSpecs,
135+
Progress: os.Stderr,
136+
Tags: git.NoTags,
137+
Force: true,
138+
Auth: credentials,
103139
})
104140
if err != nil && err != git.NoErrAlreadyUpToDate {
105141
return errors.Wrap(err, "Error doing Git fetch.")

internal/pull/pull_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ func TestPullGitFresh(t *testing.T) {
9494
// It is expected that we still pull these even though they don't match the expected pattern. We just ignore them later on.
9595
"bd82b85707bc13904e3526517677039d4da4a9bb refs/remotes/origin/heads/very-ignored-branch",
9696
"bd82b85707bc13904e3526517677039d4da4a9bb refs/remotes/origin/tags/an-ignored-tag-too",
97+
"26936381e619a01122ea33993e3cebc474496805 refs/remotes/origin/heads/a-ref-that-will-need-pruning",
9798
})
9899
}
99100

@@ -125,11 +126,9 @@ func TestPullGitNotFreshWithChanges(t *testing.T) {
125126
"b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/remotes/origin/heads/main",
126127
"26936381e619a01122ea33993e3cebc474496805 refs/remotes/origin/heads/v1",
127128
"33d42021633d74bcd0bf9c95e3d3159131a5faa7 refs/remotes/origin/heads/v3", // v3 was force-pushed, and should have been force-pulled too.
128-
"26936381e619a01122ea33993e3cebc474496805 refs/remotes/origin/tags/v2",
129129
"42d077b4730d1ba413f7bb7e0fa7c98653fb0c78 refs/remotes/origin/heads/v4", // v4 is a new branch.
130-
// We deleted these, but we don't currently do any pruning.
131-
"bd82b85707bc13904e3526517677039d4da4a9bb refs/remotes/origin/heads/very-ignored-branch",
132130
"bd82b85707bc13904e3526517677039d4da4a9bb refs/remotes/origin/tags/an-ignored-tag-too",
131+
"26936381e619a01122ea33993e3cebc474496805 refs/remotes/origin/heads/a-ref-that-will-need-pruning/because-it-now-has-this-extra-bit",
133132
})
134133
}
135134

internal/pull/pull_test/codeql-action-initial.git/packed-refs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pack-refs with: peeled fully-peeled sorted
2+
26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning
23
b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main
34
26936381e619a01122ea33993e3cebc474496805 refs/heads/v1
45
e529a54fad10a936308b2220e05f7f00757f8e7c refs/heads/v3
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pack-refs with: peeled fully-peeled sorted
2+
26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning/because-it-now-has-this-extra-bit
23
b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main
34
26936381e619a01122ea33993e3cebc474496805 refs/heads/v1
45
33d42021633d74bcd0bf9c95e3d3159131a5faa7 refs/heads/v3
56
42d077b4730d1ba413f7bb7e0fa7c98653fb0c78 refs/heads/v4
6-
26936381e619a01122ea33993e3cebc474496805 refs/tags/v2
7+
bd82b85707bc13904e3526517677039d4da4a9bb refs/tags/an-ignored-tag-too

0 commit comments

Comments
 (0)