Skip to content

Commit

Permalink
[PRETEST]: Added support for bare repo in clone function of git module (
Browse files Browse the repository at this point in the history
#419)

* Added support for bare repo in clone fn

Signed-off-by: Manoramsharma <[email protected]>

* Fixes

Signed-off-by: Manoramsharma <[email protected]>

* Fixed CI failure

Signed-off-by: Manoramsharma <[email protected]>

* Added test scenarios for clone function

Signed-off-by: Manoramsharma <[email protected]>

* fixed the failing test

Signed-off-by: Manoramsharma <[email protected]>

---------

Signed-off-by: Manoramsharma <[email protected]>
  • Loading branch information
Manoramsharma authored Aug 12, 2024
1 parent ecbd431 commit 1467eaa
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 99 deletions.
59 changes: 20 additions & 39 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,40 +110,6 @@ func (cloneOpts *CloneOptions) Validate() error {
return nil
}

// Clone clones a git repository
func (cloneOpts *CloneOptions) cloneBare() (*git.Repository, error) {
args := []string{"clone", "--bare"}
if cloneOpts.Commit != "" {
args = append(args, "--no-checkout")
}
args = append(args, cloneOpts.RepoURL, cloneOpts.LocalPath)

cmd := exec.Command("git", args...)
cmd.Stdout = cloneOpts.Writer
cmd.Stderr = cloneOpts.Writer

if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to clone bare repository: %w", err)
}

repo, err := git.PlainOpen(cloneOpts.LocalPath)
if err != nil {
return nil, err
}

if cloneOpts.Commit != "" {
cmd = exec.Command("git", "update-ref", "HEAD", cloneOpts.Commit)
cmd.Dir = cloneOpts.LocalPath
cmd.Stdout = cloneOpts.Writer
cmd.Stderr = cloneOpts.Writer
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to update HEAD to specified commit: %w", err)
}
}

return repo, nil
}

// CheckoutFromBare checks out the specified reference from a bare repository
func (cloneOpts *CloneOptions) CheckoutFromBare() error {
if !cloneOpts.Bare {
Expand Down Expand Up @@ -176,12 +142,31 @@ func (cloneOpts *CloneOptions) CheckoutFromBare() error {
return nil
}

// Clone clones a git repository
// Clone clones a git repository, handling both bare and non-bare options
func (cloneOpts *CloneOptions) Clone() (*git.Repository, error) {
if err := cloneOpts.Validate(); err != nil {
return nil, err
}

if cloneOpts.Bare {
// Use local git command to clone as bare repository
cmdArgs := []string{"clone", "--bare", cloneOpts.RepoURL, cloneOpts.LocalPath}
cmd := exec.Command("git", cmdArgs...)

output, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("failed to clone repository: %s, error: %w", string(output), err)
}

repo, err := git.PlainOpen(cloneOpts.LocalPath)
if err != nil {
return nil, err
}

return repo, nil
}

// Default non-bare clone using go-getter
url, err := cloneOpts.ForceGitUrl()
if err != nil {
return nil, err
Expand Down Expand Up @@ -220,10 +205,6 @@ func CloneWithOpts(opts ...CloneOption) (*git.Repository, error) {
return nil, err
}

if cloneOpts.Bare {
return cloneOpts.cloneBare()
}

return cloneOpts.Clone()
}

Expand Down
194 changes: 134 additions & 60 deletions pkg/git/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package git

import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"

Expand Down Expand Up @@ -51,66 +53,138 @@ func TestValidateGitOptions(t *testing.T) {
func TestCloneWithOptions(t *testing.T) {
var buf bytes.Buffer

tmpdir, err := os.MkdirTemp("", "git")
tmpdir = filepath.Join(tmpdir, "git")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.Equal(t, rErr, nil)
}()

repo, err := CloneWithOpts(
WithRepoURL("https://github.com/KusionStack/catalog.git"),
WithCommit("4e59d5852cd7"),
WithWriter(&buf),
WithLocalPath(tmpdir),
)
assert.Equal(t, err, nil)

head, err := repo.Head()
assert.Equal(t, err, nil)
assert.Equal(t, head.Hash().String(), "4e59d5852cd76542f9f0ec65e5773ca9f4e02462")
assert.Equal(t, err, nil)
}

func TestCloneWithOptionsBare(t *testing.T) {
var buf bytes.Buffer
tmpdir, err := os.MkdirTemp("", "git-bare")
assert.NilError(t, err)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.NilError(t, rErr)
}()

commitSHA := "4e59d5852cd76542f9f0ec65e5773ca9f4e02462"
repo, err := CloneWithOpts(
WithRepoURL("https://github.com/KusionStack/catalog.git"),
WithCommit(commitSHA),
WithWriter(&buf),
WithLocalPath(tmpdir),
WithBare(true),
)
if err != nil {
t.Fatalf("Failed to clone bare repository: %v\nBuffer contents:\n%s", err, buf.String())
}

// Verify that the repository is bare
config, err := repo.Config()
assert.NilError(t, err)
assert.Equal(t, config.Core.IsBare, true, "Expected repository to be bare")

// Verify that the repository is bare by checking for the absence of a .git directory
// and the presence of HEAD file in the root directory
_, err = os.Stat(filepath.Join(tmpdir, ".git"))
assert.Assert(t, os.IsNotExist(err), "Expected .git directory to not exist in a bare repo")

_, err = os.Stat(filepath.Join(tmpdir, "HEAD"))
assert.NilError(t, err, "Expected HEAD file to exist in bare repo root")

// Verify that HEAD points to the specified commit
head, err := repo.Head()
assert.NilError(t, err)
assert.Equal(t, head.Hash().String(), commitSHA, "Expected HEAD to point to the specified commit")
// Test cloning a remote repo as a bare repo
t.Run("RemoteBareClone", func(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "git_bare")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.Equal(t, rErr, nil)
}()

_, err = CloneWithOpts(
WithRepoURL("https://github.com/KusionStack/catalog.git"),
WithLocalPath(tmpdir),
WithBare(true), // Set the Bare flag to true
)
assert.Equal(t, err, nil)

// Verify the directory is a bare repository
_, err = os.Stat(filepath.Join(tmpdir, "HEAD"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "config"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "objects"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "refs"))
assert.Equal(t, os.IsNotExist(err), false)
})

// Test cloning a remote repo as a normal repo and checking out a commit
t.Run("RemoteNonBareCloneWithCommit", func(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "git_non_bare")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.Equal(t, rErr, nil)
}()

repo, err := CloneWithOpts(
WithRepoURL("https://github.com/KusionStack/catalog.git"),
WithCommit("4e59d5852cd76542f9f0ec65e5773ca9f4e02462"),
WithWriter(&buf),
WithLocalPath(tmpdir),
WithBare(false), // Ensure the Bare flag is false
)
assert.Equal(t, err, nil)

head, err := repo.Head()
assert.Equal(t, err, nil)
assert.Equal(t, head.Hash().String(), "4e59d5852cd76542f9f0ec65e5773ca9f4e02462")
})

// Test cloning a bare repo as a bare repo
t.Run("LocalBareCloneAsBare", func(t *testing.T) {
// Setup a local bare repository
bareRepoPath, err := os.MkdirTemp("", "local_bare_repo")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(bareRepoPath)
assert.Equal(t, rErr, nil)
}()
cmd := exec.Command("git", "clone", "--bare", "https://github.com/KusionStack/catalog.git", bareRepoPath)
err = cmd.Run()
assert.Equal(t, err, nil)

// Clone the local bare repository as a bare repository
tmpdir, err := os.MkdirTemp("", "clone_bare_repo")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.Equal(t, rErr, nil)
}()

_, err = CloneWithOpts(
WithRepoURL(bareRepoPath),
WithLocalPath(tmpdir),
WithBare(true), // Set the Bare flag to true
)
assert.Equal(t, err, nil)

// Verify the directory is a bare repository
_, err = os.Stat(filepath.Join(tmpdir, "HEAD"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "config"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "objects"))
assert.Equal(t, os.IsNotExist(err), false)

_, err = os.Stat(filepath.Join(tmpdir, "refs"))
assert.Equal(t, os.IsNotExist(err), false)
})

// Test cloning a bare repo as a normal repo and checking out a commit
t.Run("LocalBareCloneAsNonBareWithCommit", func(t *testing.T) {
// Setup a local bare repository
bareRepoPath, err := os.MkdirTemp("", "local_bare_repo")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(bareRepoPath)
assert.Equal(t, rErr, nil)
}()
cmd := exec.Command("git", "clone", "--bare", "https://github.com/KusionStack/catalog.git", bareRepoPath)
err = cmd.Run()
assert.Equal(t, err, nil)

// Construct the file URL for the local bare repository
bareRepoURL := fmt.Sprintf("file://%s", bareRepoPath)

// Clone the local bare repository as a normal repository and checkout a commit
tmpdir, err := os.MkdirTemp("", "clone_non_bare_repo")
assert.Equal(t, err, nil)
defer func() {
rErr := os.RemoveAll(tmpdir)
assert.Equal(t, rErr, nil)
}()

repo, err := CloneWithOpts(
WithRepoURL(bareRepoURL),
WithCommit("4e59d5852cd76542f9f0ec65e5773ca9f4e02462"),
WithWriter(&buf),
WithLocalPath(tmpdir),
WithBare(false), // Ensure the Bare flag is false
)
assert.Equal(t, err, nil)

head, err := repo.Head()
assert.Equal(t, err, nil)
assert.Equal(t, head.Hash().String(), "4e59d5852cd76542f9f0ec65e5773ca9f4e02462")
})
}

func TestCheckoutFromBare(t *testing.T) {
Expand Down

0 comments on commit 1467eaa

Please sign in to comment.