blob: 258601bda36d9b18ccfa3fb59e24dc1b7c238d62 [file] [log] [blame] [edit]
// Copyright 2020-2024 Buf Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package git
import (
"context"
"regexp"
"github.com/bufbuild/buf/private/pkg/app"
"github.com/bufbuild/buf/private/pkg/command"
"github.com/bufbuild/buf/private/pkg/storage"
"github.com/bufbuild/buf/private/pkg/storage/storageos"
"github.com/bufbuild/buf/private/pkg/tracing"
"go.uber.org/zap"
)
// Name is a name identifiable by git.
type Name interface {
// If cloneBranch returns a non-empty string, any clones will be performed with --branch set to the value.
cloneBranch() string
// If checkout returns a non-empty string, a checkout of the value will be performed after cloning.
checkout() string
}
// NewBranchName returns a new Name for the branch.
func NewBranchName(branch string) Name {
return newBranch(branch)
}
// NewTagName returns a new Name for the tag.
func NewTagName(tag string) Name {
return newBranch(tag)
}
// NewRefName returns a new Name for the ref.
func NewRefName(ref string) Name {
return newRef(ref)
}
// NewRefNameWithBranch returns a new Name for the ref while setting branch as the clone target.
func NewRefNameWithBranch(ref string, branch string) Name {
return newRefWithBranch(ref, branch)
}
// Cloner clones git repositories to buckets.
type Cloner interface {
// CloneToBucket clones the repository to the bucket.
//
// The url must contain the scheme, including file:// if necessary.
// depth must be > 0.
CloneToBucket(
ctx context.Context,
envContainer app.EnvContainer,
url string,
depth uint32,
writeBucket storage.WriteBucket,
options CloneToBucketOptions,
) error
}
// CloneToBucketOptions are options for Clone.
type CloneToBucketOptions struct {
Mapper storage.Mapper
Name Name
RecurseSubmodules bool
}
// NewCloner returns a new Cloner.
func NewCloner(
logger *zap.Logger,
tracer tracing.Tracer,
storageosProvider storageos.Provider,
runner command.Runner,
options ClonerOptions,
) Cloner {
return newCloner(logger, tracer, storageosProvider, runner, options)
}
// ClonerOptions are options for a new Cloner.
type ClonerOptions struct {
HTTPSUsernameEnvKey string
HTTPSPasswordEnvKey string
SSHKeyFileEnvKey string
SSHKnownHostsFilesEnvKey string
}
// Lister lists files in git repositories.
type Lister interface {
// ListFilesAndUnstagedFiles lists all files checked into git except those that
// were deleted, and also lists unstaged files.
//
// This does not list unstaged deleted files
// This does not list unignored files that were not added.
// This ignores regular files.
//
// This is used for situations like license headers where we want all the
// potential git files during development.
//
// The returned paths will be unnormalized.
//
// This is the equivalent of doing:
//
// comm -23 \
// <(git ls-files --cached --modified --others --no-empty-directory --exclude-standard | sort -u | grep -v -e IGNORE_PATH1 -e IGNORE_PATH2) \
// <(git ls-files --deleted | sort -u)
ListFilesAndUnstagedFiles(
ctx context.Context,
envContainer app.EnvStdioContainer,
options ListFilesAndUnstagedFilesOptions,
) ([]string, error)
}
// NewLister returns a new Lister.
func NewLister(runner command.Runner) Lister {
return newLister(runner)
}
// ListFilesAndUnstagedFilesOptions are options for ListFilesAndUnstagedFiles.
type ListFilesAndUnstagedFilesOptions struct {
// IgnorePathRegexps are regexes of paths to ignore.
//
// These must be unnormalized in the manner of the local OS that the Lister
// is being applied to.
IgnorePathRegexps []*regexp.Regexp
}