Skip to content

Commit b054fbd

Browse files
committed
Prevent panic when cloning empty git repository
This covers the edge case in which a user creates a GitRepository CR referencing an empty Git repository. Currently, the controller will panic in this situation since the returned commit pointer is nil. Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
1 parent ae3a81e commit b054fbd

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

api/v1beta2/gitrepository_types.go

+4
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ const (
258258
// GitOperationFailedReason signals that a Git operation (e.g. clone,
259259
// checkout, etc.) failed.
260260
GitOperationFailedReason string = "GitOperationFailed"
261+
262+
// GitEmptyRepositoryReason signals that a referenced Git repository is empty
263+
// (only has an initial branch without any commits).
264+
GitEmptyRepositoryReason string = "GitEmptyRepository"
261265
)
262266

263267
// GetConditions returns the status conditions of the object.

controllers/gitrepository_controller.go

+8
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,14 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
537537
if err != nil {
538538
return sreconcile.ResultEmpty, err
539539
}
540+
if c == nil {
541+
e := serror.NewGeneric(
542+
fmt.Errorf("git repository is empty"),
543+
sourcev1.GitEmptyRepositoryReason,
544+
)
545+
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
546+
return sreconcile.ResultEmpty, e
547+
}
540548
// Assign the commit to the shared commit reference.
541549
*commit = *c
542550

controllers/gitrepository_controller_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,65 @@ func TestGitRepositoryReconciler_Reconcile(t *testing.T) {
220220
testSuspendedObjectDeleteWithArtifact(ctx, g, obj)
221221
}
222222

223+
func TestGitRepositoryReconciler_reconcileSource_emptyRepository(t *testing.T) {
224+
g := NewWithT(t)
225+
226+
server, err := gittestserver.NewTempGitServer()
227+
g.Expect(err).NotTo(HaveOccurred())
228+
defer os.RemoveAll(server.Root())
229+
server.AutoCreate()
230+
g.Expect(server.StartHTTP()).To(Succeed())
231+
defer server.StopHTTP()
232+
233+
obj := &sourcev1.GitRepository{
234+
ObjectMeta: metav1.ObjectMeta{
235+
GenerateName: "empty-",
236+
Generation: 1,
237+
},
238+
Spec: sourcev1.GitRepositorySpec{
239+
Interval: metav1.Duration{Duration: interval},
240+
Timeout: &metav1.Duration{Duration: timeout},
241+
URL: server.HTTPAddress() + "/test.git",
242+
},
243+
}
244+
245+
fs := memfs.New()
246+
localRepo, err := gogit.Init(memory.NewStorage(), fs)
247+
g.Expect(err).NotTo(HaveOccurred())
248+
249+
builder := fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme())
250+
251+
r := &GitRepositoryReconciler{
252+
Client: builder.Build(),
253+
EventRecorder: record.NewFakeRecorder(32),
254+
Storage: testStorage,
255+
patchOptions: getPatchOptions(gitRepositoryReadyCondition.Owned, "sc"),
256+
}
257+
258+
tmpDir := t.TempDir()
259+
260+
head, _ := localRepo.Head()
261+
g.Expect(head).To(BeNil())
262+
263+
g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
264+
defer func() {
265+
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
266+
}()
267+
268+
var commit git.Commit
269+
var includes artifactSet
270+
sp := patch.NewSerialPatcher(obj, r.Client)
271+
272+
got, err := r.reconcileSource(context.TODO(), sp, obj, &commit, &includes, tmpDir)
273+
assertConditions := []metav1.Condition{
274+
*conditions.TrueCondition(sourcev1.FetchFailedCondition, sourcev1.GitEmptyRepositoryReason, "git repository is empty"),
275+
}
276+
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(assertConditions))
277+
g.Expect(err).To(HaveOccurred())
278+
g.Expect(got).To(Equal(sreconcile.ResultEmpty))
279+
g.Expect(commit).ToNot(BeNil())
280+
}
281+
223282
func TestGitRepositoryReconciler_reconcileSource_authStrategy(t *testing.T) {
224283
type options struct {
225284
username string

0 commit comments

Comments
 (0)