aboutsummaryrefslogtreecommitdiffstats
path: root/repository.go
diff options
context:
space:
mode:
Diffstat (limited to 'repository.go')
-rw-r--r--repository.go60
1 files changed, 47 insertions, 13 deletions
diff --git a/repository.go b/repository.go
index 3154ac0..1524a69 100644
--- a/repository.go
+++ b/repository.go
@@ -22,6 +22,7 @@ import (
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/internal/path_util"
"github.com/go-git/go-git/v5/internal/revision"
+ "github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
formatcfg "github.com/go-git/go-git/v5/plumbing/format/config"
@@ -62,6 +63,7 @@ var (
ErrUnableToResolveCommit = errors.New("unable to resolve commit")
ErrPackedObjectsNotSupported = errors.New("packed objects not supported")
ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support")
+ ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme")
)
// Repository represents a git repository
@@ -96,6 +98,10 @@ func InitWithOptions(s storage.Storer, worktree billy.Filesystem, options InitOp
options.DefaultBranch = plumbing.Master
}
+ if err := options.DefaultBranch.Validate(); err != nil {
+ return nil, err
+ }
+
r := newRepository(s, worktree)
_, err := r.Reference(plumbing.HEAD, false)
switch err {
@@ -235,9 +241,19 @@ func CloneContext(
// if the repository will have worktree (non-bare) or not (bare), if the path
// is not empty ErrRepositoryAlreadyExists is returned.
func PlainInit(path string, isBare bool) (*Repository, error) {
+ return PlainInitWithOptions(path, &PlainInitOptions{
+ Bare: isBare,
+ })
+}
+
+func PlainInitWithOptions(path string, opts *PlainInitOptions) (*Repository, error) {
+ if opts == nil {
+ opts = &PlainInitOptions{}
+ }
+
var wt, dot billy.Filesystem
- if isBare {
+ if opts.Bare {
dot = osfs.New(path)
} else {
wt = osfs.New(path)
@@ -246,16 +262,7 @@ func PlainInit(path string, isBare bool) (*Repository, error) {
s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
- return Init(s, wt)
-}
-
-func PlainInitWithOptions(path string, opts *PlainInitOptions) (*Repository, error) {
- wt := osfs.New(path)
- dot, _ := wt.Chroot(GitDirName)
-
- s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
-
- r, err := Init(s, wt)
+ r, err := InitWithOptions(s, wt, opts.InitOptions)
if err != nil {
return nil, err
}
@@ -265,7 +272,7 @@ func PlainInitWithOptions(path string, opts *PlainInitOptions) (*Repository, err
return nil, err
}
- if opts != nil {
+ if opts.ObjectFormat != "" {
if opts.ObjectFormat == formatcfg.SHA256 && hash.CryptoType != crypto.SHA256 {
return nil, ErrSHA256NotSupported
}
@@ -721,7 +728,10 @@ func (r *Repository) DeleteBranch(name string) error {
// CreateTag creates a tag. If opts is included, the tag is an annotated tag,
// otherwise a lightweight tag is created.
func (r *Repository) CreateTag(name string, hash plumbing.Hash, opts *CreateTagOptions) (*plumbing.Reference, error) {
- rname := plumbing.ReferenceName(path.Join("refs", "tags", name))
+ rname := plumbing.NewTagReferenceName(name)
+ if err := rname.Validate(); err != nil {
+ return nil, err
+ }
_, err := r.Storer.Reference(rname)
switch err {
@@ -886,6 +896,30 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
return err
}
+ // When the repository to clone is on the local machine,
+ // instead of using hard links, automatically setup .git/objects/info/alternates
+ // to share the objects with the source repository
+ if o.Shared {
+ if !url.IsLocalEndpoint(o.URL) {
+ return ErrAlternatePathNotSupported
+ }
+ altpath := o.URL
+ remoteRepo, err := PlainOpen(o.URL)
+ if err != nil {
+ return fmt.Errorf("failed to open remote repository: %w", err)
+ }
+ conf, err := remoteRepo.Config()
+ if err != nil {
+ return fmt.Errorf("failed to read remote repository configuration: %w", err)
+ }
+ if !conf.Core.IsBare {
+ altpath = path.Join(altpath, GitDirName)
+ }
+ if err := r.Storer.AddAlternate(altpath); err != nil {
+ return fmt.Errorf("failed to add alternate file to git objects dir: %w", err)
+ }
+ }
+
ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
RefSpecs: c.Fetch,
Depth: o.Depth,