239 lines
5.8 KiB
Go
239 lines
5.8 KiB
Go
// Copyright 2023 Harness, 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"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/harness/gitness/errors"
|
|
"github.com/harness/gitness/git/types"
|
|
)
|
|
|
|
type GetCommitParams struct {
|
|
ReadParams
|
|
// SHA is the git commit sha
|
|
SHA string
|
|
}
|
|
|
|
type Commit struct {
|
|
SHA string `json:"sha"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message,omitempty"`
|
|
Author Signature `json:"author"`
|
|
Committer Signature `json:"committer"`
|
|
}
|
|
|
|
type GetCommitOutput struct {
|
|
Commit Commit `json:"commit"`
|
|
}
|
|
|
|
type Signature struct {
|
|
Identity Identity `json:"identity"`
|
|
When time.Time `json:"when"`
|
|
}
|
|
|
|
type Identity struct {
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
func (i *Identity) Validate() error {
|
|
if i.Name == "" {
|
|
return errors.InvalidArgument("identity name is mandatory")
|
|
}
|
|
|
|
if i.Email == "" {
|
|
return errors.InvalidArgument("identity email is mandatory")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) GetCommit(ctx context.Context, params *GetCommitParams) (*GetCommitOutput, error) {
|
|
if params == nil {
|
|
return nil, ErrNoParamsProvided
|
|
}
|
|
if !isValidGitSHA(params.SHA) {
|
|
return nil, errors.InvalidArgument("the provided commit sha '%s' is of invalid format.", params.SHA)
|
|
}
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
result, err := s.adapter.GetCommit(ctx, repoPath, params.SHA)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
commit, err := mapCommit(result)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map rpc commit: %w", err)
|
|
}
|
|
|
|
return &GetCommitOutput{
|
|
Commit: *commit,
|
|
}, nil
|
|
}
|
|
|
|
type ListCommitsParams struct {
|
|
ReadParams
|
|
// GitREF is a git reference (branch / tag / commit SHA)
|
|
GitREF string
|
|
// After is a git reference (branch / tag / commit SHA)
|
|
// If provided, commits only up to that reference will be returned (exlusive)
|
|
After string
|
|
Page int32
|
|
Limit int32
|
|
Path string
|
|
|
|
// Since allows to filter for commits since the provided UNIX timestamp - Optional, ignored if value is 0.
|
|
Since int64
|
|
|
|
// Until allows to filter for commits until the provided UNIX timestamp - Optional, ignored if value is 0.
|
|
Until int64
|
|
|
|
// Committer allows to filter for commits based on the committer - Optional, ignored if string is empty.
|
|
Committer string
|
|
}
|
|
|
|
type RenameDetails struct {
|
|
OldPath string
|
|
NewPath string
|
|
CommitShaBefore string
|
|
CommitShaAfter string
|
|
}
|
|
|
|
type ListCommitsOutput struct {
|
|
Commits []Commit
|
|
RenameDetails []*RenameDetails
|
|
TotalCommits int
|
|
}
|
|
|
|
func (s *Service) ListCommits(ctx context.Context, params *ListCommitsParams) (*ListCommitsOutput, error) {
|
|
if params == nil {
|
|
return nil, ErrNoParamsProvided
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
gitCommits, renameDetails, err := s.adapter.ListCommits(
|
|
ctx,
|
|
repoPath,
|
|
params.GitREF,
|
|
int(params.Page),
|
|
int(params.Limit),
|
|
types.CommitFilter{
|
|
AfterRef: params.After,
|
|
Path: params.Path,
|
|
Since: params.Since,
|
|
Until: params.Until,
|
|
Committer: params.Committer,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// try to get total commits between gitref and After refs
|
|
totalCommits := 0
|
|
if params.Page == 1 && len(gitCommits) < int(params.Limit) {
|
|
totalCommits = len(gitCommits)
|
|
} else if params.After != "" && params.GitREF != params.After {
|
|
div, err := s.adapter.GetCommitDivergences(ctx, repoPath, []types.CommitDivergenceRequest{
|
|
{From: params.GitREF, To: params.After},
|
|
}, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(div) > 0 {
|
|
totalCommits = int(div[0].Ahead)
|
|
}
|
|
}
|
|
|
|
commits := make([]Commit, len(gitCommits))
|
|
for i := range gitCommits {
|
|
commit, err := mapCommit(&gitCommits[i])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map rpc commit: %w", err)
|
|
}
|
|
commits[i] = *commit
|
|
}
|
|
|
|
return &ListCommitsOutput{
|
|
Commits: commits,
|
|
RenameDetails: mapRenameDetails(renameDetails),
|
|
TotalCommits: totalCommits,
|
|
}, nil
|
|
}
|
|
|
|
type GetCommitDivergencesParams struct {
|
|
ReadParams
|
|
MaxCount int32
|
|
Requests []CommitDivergenceRequest
|
|
}
|
|
|
|
type GetCommitDivergencesOutput struct {
|
|
Divergences []types.CommitDivergence
|
|
}
|
|
|
|
// CommitDivergenceRequest contains the refs for which the converging commits should be counted.
|
|
type CommitDivergenceRequest struct {
|
|
// From is the ref from which the counting of the diverging commits starts.
|
|
From string
|
|
// To is the ref at which the counting of the diverging commits ends.
|
|
To string
|
|
}
|
|
|
|
// CommitDivergence contains the information of the count of converging commits between two refs.
|
|
type CommitDivergence struct {
|
|
// Ahead is the count of commits the 'From' ref is ahead of the 'To' ref.
|
|
Ahead int32
|
|
// Behind is the count of commits the 'From' ref is behind the 'To' ref.
|
|
Behind int32
|
|
}
|
|
|
|
func (s *Service) GetCommitDivergences(
|
|
ctx context.Context,
|
|
params *GetCommitDivergencesParams,
|
|
) (*GetCommitDivergencesOutput, error) {
|
|
if params == nil {
|
|
return nil, ErrNoParamsProvided
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
requests := make([]types.CommitDivergenceRequest, len(params.Requests))
|
|
for i, req := range params.Requests {
|
|
requests[i] = types.CommitDivergenceRequest{
|
|
From: req.From,
|
|
To: req.To,
|
|
}
|
|
}
|
|
|
|
// call gitea
|
|
divergences, err := s.adapter.GetCommitDivergences(
|
|
ctx,
|
|
repoPath,
|
|
requests,
|
|
params.MaxCount,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &GetCommitDivergencesOutput{
|
|
Divergences: divergences,
|
|
}, nil
|
|
}
|