fix commit adn files changed counters

This commit is contained in:
Enver Bisevac 2023-08-11 13:29:25 +02:00
parent d2c04cf42c
commit 63145686f4
16 changed files with 2358 additions and 2155 deletions

View File

@ -9,6 +9,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"strconv"
"time" "time"
"github.com/harness/gitness/gitrpc/rpc" "github.com/harness/gitness/gitrpc/rpc"
@ -97,6 +98,7 @@ type RenameDetails struct {
type ListCommitsOutput struct { type ListCommitsOutput struct {
Commits []Commit Commits []Commit
RenameDetails []*RenameDetails RenameDetails []*RenameDetails
TotalCommits int
} }
func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*ListCommitsOutput, error) { func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*ListCommitsOutput, error) {
@ -122,6 +124,21 @@ func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*L
Commits: make([]Commit, 0, 16), Commits: make([]Commit, 0, 16),
} }
// check for list commits header
header, err := stream.Header()
if err != nil {
return nil, processRPCErrorf(err, "failed to read list commits header from stream")
}
values := header.Get("total-commits")
if len(values) > 0 && values[0] != "" {
total, err := strconv.ParseInt(values[0], 10, 32)
if err != nil {
return nil, processRPCErrorf(err, "failed to convert header total-commits")
}
output.TotalCommits = int(total)
}
for { for {
var next *rpc.ListCommitsResponse var next *rpc.ListCommitsResponse
next, err = stream.Recv() next, err = stream.Recv()

View File

@ -6,12 +6,14 @@ package service
import ( import (
"context" "context"
"strconv"
"github.com/harness/gitness/gitrpc/internal/types" "github.com/harness/gitness/gitrpc/internal/types"
"github.com/harness/gitness/gitrpc/rpc" "github.com/harness/gitness/gitrpc/rpc"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
@ -65,7 +67,27 @@ func (s RepositoryService) ListCommits(request *rpc.ListCommitsRequest,
return processGitErrorf(err, "failed to get list of commits") return processGitErrorf(err, "failed to get list of commits")
} }
// try to get total commits between gitref and After refs
totalCommits := 0
if request.Page == 1 && len(gitCommits) < int(request.Limit) {
totalCommits = len(gitCommits)
} else if request.After != "" && request.GitRef != request.After {
div, err := s.adapter.GetCommitDivergences(ctx, repoPath, []types.CommitDivergenceRequest{
{From: request.GitRef, To: request.After},
}, 0)
if err != nil {
return processGitErrorf(err, "failed to get total commits")
}
if len(div) > 0 {
totalCommits = int(div[0].Ahead)
}
}
log.Ctx(ctx).Trace().Msgf("git adapter returned %d commits", len(gitCommits)) log.Ctx(ctx).Trace().Msgf("git adapter returned %d commits", len(gitCommits))
header := metadata.New(map[string]string{"total-commits": strconv.Itoa(totalCommits)})
if err := stream.SendHeader(header); err != nil {
return ErrInternalf("unable to send 'total-commits' header", err)
}
for i := range gitCommits { for i := range gitCommits {
var commit *rpc.Commit var commit *rpc.Commit

View File

@ -20,14 +20,14 @@ import (
* ListCommits lists the commits of a repo. * ListCommits lists the commits of a repo.
*/ */
func (c *Controller) ListCommits(ctx context.Context, session *auth.Session, func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
repoRef string, gitRef string, filter *types.CommitFilter) ([]types.Commit, []types.RenameDetails, error) { repoRef string, gitRef string, filter *types.CommitFilter) (types.ListCommitResponse, error) {
repo, err := c.repoStore.FindByRef(ctx, repoRef) repo, err := c.repoStore.FindByRef(ctx, repoRef)
if err != nil { if err != nil {
return nil, nil, err return types.ListCommitResponse{}, err
} }
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil { if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil {
return nil, nil, err return types.ListCommitResponse{}, err
} }
// set gitRef to default branch in case an empty reference was provided // set gitRef to default branch in case an empty reference was provided
@ -47,7 +47,7 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
Committer: filter.Committer, Committer: filter.Committer,
}) })
if err != nil { if err != nil {
return nil, nil, err return types.ListCommitResponse{}, err
} }
commits := make([]types.Commit, len(rpcOut.Commits)) commits := make([]types.Commit, len(rpcOut.Commits))
@ -55,7 +55,7 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
var commit *types.Commit var commit *types.Commit
commit, err = controller.MapCommit(&rpcOut.Commits[i]) commit, err = controller.MapCommit(&rpcOut.Commits[i])
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to map commit: %w", err) return types.ListCommitResponse{}, fmt.Errorf("failed to map commit: %w", err)
} }
commits[i] = *commit commits[i] = *commit
} }
@ -64,9 +64,13 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
for i := range rpcOut.RenameDetails { for i := range rpcOut.RenameDetails {
renameDetails := controller.MapRenameDetails(rpcOut.RenameDetails[i]) renameDetails := controller.MapRenameDetails(rpcOut.RenameDetails[i])
if renameDetails == nil { if renameDetails == nil {
return nil, nil, fmt.Errorf("rename details was nil") return types.ListCommitResponse{}, fmt.Errorf("rename details was nil")
} }
renameDetailList[i] = *renameDetails renameDetailList[i] = *renameDetails
} }
return commits, renameDetailList, nil return types.ListCommitResponse{
Commits: commits,
RenameDetails: renameDetailList,
TotalCommits: rpcOut.TotalCommits,
}, nil
} }

View File

@ -43,3 +43,26 @@ func HandleDiff(repoCtrl *repo.Controller) http.HandlerFunc {
render.JSONArrayDynamic(ctx, w, stream) render.JSONArrayDynamic(ctx, w, stream)
} }
} }
// HandleDiffStats how diff statistics of two commits, branches or tags.
func HandleDiffStats(repoCtrl *repo.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
repoRef, err := request.GetRepoRefFromPath(r)
if err != nil {
render.TranslatedUserError(w, err)
return
}
path := request.GetOptionalRemainderFromPath(r)
output, err := repoCtrl.DiffStats(ctx, session, repoRef, path)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.JSON(w, http.StatusOK, output)
}
}

View File

@ -10,7 +10,6 @@ import (
"github.com/harness/gitness/internal/api/controller/repo" "github.com/harness/gitness/internal/api/controller/repo"
"github.com/harness/gitness/internal/api/render" "github.com/harness/gitness/internal/api/render"
"github.com/harness/gitness/internal/api/request" "github.com/harness/gitness/internal/api/request"
"github.com/harness/gitness/types"
) )
/* /*
@ -34,20 +33,15 @@ func HandleListCommits(repoCtrl *repo.Controller) http.HandlerFunc {
return return
} }
commits, renameDetails, err := repoCtrl.ListCommits(ctx, session, repoRef, gitRef, filter) list, err := repoCtrl.ListCommits(ctx, session, repoRef, gitRef, filter)
if err != nil { if err != nil {
render.TranslatedUserError(w, err) render.TranslatedUserError(w, err)
return return
} }
commitsResponse := types.ListCommitResponse{
Commits: commits,
RenameDetails: renameDetails,
}
// TODO: get last page indicator explicitly - current check is wrong in case len % limit == 0 // TODO: get last page indicator explicitly - current check is wrong in case len % limit == 0
isLastPage := len(commits) < filter.Limit isLastPage := len(list.Commits) < filter.Limit
render.PaginationNoTotal(r, w, filter.Page, filter.Limit, isLastPage) render.PaginationNoTotal(r, w, filter.Page, filter.Limit, isLastPage)
render.JSON(w, http.StatusOK, commitsResponse) render.JSON(w, http.StatusOK, list)
} }
} }

View File

@ -661,13 +661,23 @@ func repoOperations(reflector *openapi3.Reflector) {
opDiff.WithTags("repository") opDiff.WithTags("repository")
opDiff.WithMapOfAnything(map[string]interface{}{"operationId": "rawDiff"}) opDiff.WithMapOfAnything(map[string]interface{}{"operationId": "rawDiff"})
_ = reflector.SetRequest(&opDiff, new(getRawDiffRequest), http.MethodGet) _ = reflector.SetRequest(&opDiff, new(getRawDiffRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opDiff, new(types.DiffStats), http.StatusOK)
_ = reflector.SetStringResponse(&opDiff, http.StatusOK, "text/plain") _ = reflector.SetStringResponse(&opDiff, http.StatusOK, "text/plain")
_ = reflector.SetJSONResponse(&opDiff, []gitrpc.FileDiff{}, http.StatusOK)
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusForbidden) _ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusForbidden)
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff/{range}", opDiff) _ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff/{range}", opDiff)
opDiffStats := openapi3.Operation{}
opDiffStats.WithTags("repository")
opDiffStats.WithMapOfAnything(map[string]interface{}{"operationId": "diffStats"})
_ = reflector.SetRequest(&opDiffStats, new(getRawDiffRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opDiffStats, new(types.DiffStats), http.StatusOK)
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusForbidden)
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff-stats/{range}", opDiffStats)
opMergeCheck := openapi3.Operation{} opMergeCheck := openapi3.Operation{}
opMergeCheck.WithTags("repository") opMergeCheck.WithTags("repository")
opMergeCheck.WithMapOfAnything(map[string]interface{}{"operationId": "mergeCheck"}) opMergeCheck.WithMapOfAnything(map[string]interface{}{"operationId": "mergeCheck"})

View File

@ -271,6 +271,9 @@ func setupRepos(r chi.Router,
r.Route("/diff", func(r chi.Router) { r.Route("/diff", func(r chi.Router) {
r.Get("/*", handlerrepo.HandleDiff(repoCtrl)) r.Get("/*", handlerrepo.HandleDiff(repoCtrl))
}) })
r.Route("/diff-stats", func(r chi.Router) {
r.Get("/*", handlerrepo.HandleDiffStats(repoCtrl))
})
r.Route("/merge-check", func(r chi.Router) { r.Route("/merge-check", func(r chi.Router) {
r.Post("/*", handlerrepo.HandleMergeCheck(repoCtrl)) r.Post("/*", handlerrepo.HandleMergeCheck(repoCtrl))
}) })

View File

@ -74,4 +74,5 @@ type RenameDetails struct {
type ListCommitResponse struct { type ListCommitResponse struct {
Commits []Commit `json:"commits"` Commits []Commit `json:"commits"`
RenameDetails []RenameDetails `json:"rename_details"` RenameDetails []RenameDetails `json:"rename_details"`
TotalCommits int `json:"total_commits,omitempty"`
} }

View File

@ -76,11 +76,13 @@ export const Changes: React.FC<ChangesProps> = ({
const [commitRange, setCommitRange] = useState<string[]>(defaultCommitRange || []) const [commitRange, setCommitRange] = useState<string[]>(defaultCommitRange || [])
const { routes } = useAppContext() const { routes } = useAppContext()
const { data: prCommits } = useGet<TypesCommit[]>({ const { data: prCommits } = useGet<{
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestMetadata?.number}/commits`, commits: TypesCommit[]
}>({
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
queryParams: { queryParams: {
git_ref: pullRequestMetadata?.source_branch, git_ref: sourceRef,
after: pullRequestMetadata?.target_branch after: targetRef
}, },
lazy: !pullRequestMetadata?.number lazy: !pullRequestMetadata?.number
}) })
@ -118,8 +120,6 @@ export const Changes: React.FC<ChangesProps> = ({
path: `/api/v1/repos/${repoMetadata?.path}/+/diff/${ path: `/api/v1/repos/${repoMetadata?.path}/+/diff/${
commitRangePath commitRangePath
? commitRangePath ? commitRangePath
: pullRequestMetadata
? `${pullRequestMetadata.merge_base_sha}...${pullRequestMetadata.source_sha}`
: `${targetRef}...${sourceRef}` : `${targetRef}...${sourceRef}`
}`, }`,
requestOptions: { requestOptions: {
@ -233,7 +233,7 @@ export const Changes: React.FC<ChangesProps> = ({
<Container flex={{ alignItems: 'center' }}> <Container flex={{ alignItems: 'center' }}>
<Render when={pullRequestMetadata?.number}> <Render when={pullRequestMetadata?.number}>
<CommitRangeDropdown <CommitRangeDropdown
allCommits={prCommits || []} allCommits={prCommits?.commits || []}
selectedCommits={commitRange} selectedCommits={commitRange}
setSelectedCommits={setCommitRange} setSelectedCommits={setCommitRange}
/> />
@ -309,8 +309,8 @@ export const Changes: React.FC<ChangesProps> = ({
repoMetadata={repoMetadata} repoMetadata={repoMetadata}
pullRequestMetadata={pullRequestMetadata} pullRequestMetadata={pullRequestMetadata}
onCommentUpdate={onCommentUpdate} onCommentUpdate={onCommentUpdate}
targetRef={pullRequestMetadata ? pullRequestMetadata.merge_base_sha : targetRef} targetRef={targetRef}
sourceRef={pullRequestMetadata ? pullRequestMetadata.source_sha : sourceRef} sourceRef={sourceRef}
/> />
))} ))}
</Layout.Vertical> </Layout.Vertical>

View File

@ -0,0 +1,27 @@
import React from 'react'
import { Container, PageError } from '@harness/uicore'
import { getErrorMessage } from 'utils/Utils'
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
interface TabContentWrapperProps {
className?: string
loading?: boolean
error?: Unknown
onRetry: () => void
}
export const TabContentWrapper: React.FC<TabContentWrapperProps> = ({
className,
loading,
error,
onRetry,
children
}) => {
return (
<Container className={className} padding="xlarge">
<LoadingSpinner visible={loading} withBorder={true} />
{error && <PageError message={getErrorMessage(error)} onClick={onRetry} />}
{!error && children}
</Container>
)
}

View File

@ -1,5 +1,5 @@
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import React, { useCallback, useEffect, useMemo, useState } from 'react' import React, { useCallback, useState } from 'react'
import { import {
Container, Container,
PageBody, PageBody,
@ -20,19 +20,17 @@ import { useAppContext } from 'AppContext'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { useStrings } from 'framework/strings' import { useStrings } from 'framework/strings'
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader' import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
import { voidFn, getErrorMessage, LIST_FETCHING_LIMIT, showToaster } from 'utils/Utils' import { getErrorMessage, showToaster } from 'utils/Utils'
import { Images } from 'images' import { Images } from 'images'
import { CodeIcon, isRefATag, makeDiffRefs } from 'utils/GitUtils' import { CodeIcon, isRefATag, makeDiffRefs } from 'utils/GitUtils'
import { CommitsView } from 'components/CommitsView/CommitsView'
import { Changes } from 'components/Changes/Changes' import { Changes } from 'components/Changes/Changes'
import type { OpenapiCreatePullReqRequest, TypesCommit, TypesPullReq } from 'services/code' import type { OpenapiCreatePullReqRequest, TypesDiffStats, TypesPullReq, TypesRepository } from 'services/code'
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner' import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
import { usePageIndex } from 'hooks/usePageIndex'
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount' import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount'
import type { DiffFileEntry } from 'utils/types'
import { MarkdownEditorWithPreview } from 'components/MarkdownEditorWithPreview/MarkdownEditorWithPreview' import { MarkdownEditorWithPreview } from 'components/MarkdownEditorWithPreview/MarkdownEditorWithPreview'
import { TabContentWrapper } from 'components/TabContentWrapper/TabContentWrapper'
import { CompareContentHeader, PRCreationType } from './CompareContentHeader/CompareContentHeader' import { CompareContentHeader, PRCreationType } from './CompareContentHeader/CompareContentHeader'
import { CompareCommits } from './CompareCommits'
import css from './Compare.module.scss' import css from './Compare.module.scss'
export default function Compare() { export default function Compare() {
@ -42,29 +40,16 @@ export default function Compare() {
const { repoMetadata, error, loading, diffRefs } = useGetRepositoryMetadata() const { repoMetadata, error, loading, diffRefs } = useGetRepositoryMetadata()
const [sourceGitRef, setSourceGitRef] = useState(diffRefs.sourceGitRef) const [sourceGitRef, setSourceGitRef] = useState(diffRefs.sourceGitRef)
const [targetGitRef, setTargetGitRef] = useState(diffRefs.targetGitRef) const [targetGitRef, setTargetGitRef] = useState(diffRefs.targetGitRef)
const [page, setPage] = usePageIndex()
const limit = LIST_FETCHING_LIMIT
const {
data: commits,
error: commitsError,
refetch,
response
} = useGet<{
commits: TypesCommit[]
}>({
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
queryParams: {
limit,
page,
git_ref: sourceGitRef,
after: targetGitRef
},
lazy: !repoMetadata
})
const [title, setTitle] = useState('') const [title, setTitle] = useState('')
const [description, setDescription] = useState('') const [description, setDescription] = useState('')
const [diffs, setDiffs] = useState<DiffFileEntry[]>([])
const { showError } = useToaster() const { showError } = useToaster()
const {
data,
error: errorStats
} = useGet<TypesDiffStats>({
path: `/api/v1/repos/${repoMetadata?.path}/+/diff-stats/${targetGitRef}...${sourceGitRef}`,
lazy: !repoMetadata
})
const { mutate: createPullRequest, loading: creatingInProgress } = useMutate<TypesPullReq>({ const { mutate: createPullRequest, loading: creatingInProgress } = useMutate<TypesPullReq>({
verb: 'POST', verb: 'POST',
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq` path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq`
@ -144,30 +129,6 @@ export default function Compare() {
repoMetadata repoMetadata
] ]
) )
const ChangesTab = useMemo(() => {
if (repoMetadata) {
return (
<Container className={css.changesContainer}>
<Changes
readOnly
repoMetadata={repoMetadata}
targetRef={targetGitRef}
sourceRef={sourceGitRef}
emptyTitle={getString('noChanges')}
emptyMessage={getString('noChangesCompare')}
onCommentUpdate={noop}
onDataReady={setDiffs}
/>
</Container>
)
}
}, [repoMetadata, sourceGitRef, targetGitRef, getString])
useEffect(() => {
if (commits?.commits?.length) {
setTitle(commits.commits[0].title as string)
}
}, [commits?.commits])
return ( return (
<Container className={css.main}> <Container className={css.main}>
@ -176,7 +137,7 @@ export default function Compare() {
title={getString('comparingChanges')} title={getString('comparingChanges')}
dataTooltipId="comparingChanges" dataTooltipId="comparingChanges"
/> />
<PageBody error={getErrorMessage(error || commitsError)} retryOnError={voidFn(refetch)} className={css.pageBody}> <PageBody error={getErrorMessage(error || errorStats)} className={css.pageBody}>
<LoadingSpinner visible={loading} /> <LoadingSpinner visible={loading} />
{repoMetadata && ( {repoMetadata && (
@ -219,7 +180,6 @@ export default function Compare() {
id="prComparing" id="prComparing"
defaultSelectedTabId="general" defaultSelectedTabId="general"
large={false} large={false}
onChange={() => setPage(1)}
tabList={[ tabList={[
{ {
id: 'general', id: 'general',
@ -259,8 +219,6 @@ export default function Compare() {
</Layout.Vertical> </Layout.Vertical>
</Container> </Container>
</Layout.Vertical> </Layout.Vertical>
{/** Fake rendering Changes Tab to get changes count - no API has it now */}
<Container style={{ display: 'none' }}>{ChangesTab}</Container>
</Container> </Container>
) )
}, },
@ -270,21 +228,17 @@ export default function Compare() {
<TabTitleWithCount <TabTitleWithCount
icon={CodeIcon.Commit} icon={CodeIcon.Commit}
title={getString('commits')} title={getString('commits')}
count={commits?.commits?.length || 0} count={data?.commits}
padding={{ left: 'medium' }} padding={{ left: 'medium' }}
/> />
), ),
panel: ( panel:
<Container padding="xlarge"> <CompareCommits
<CommitsView repoMetadata={repoMetadata as TypesRepository}
commits={commits?.commits || []} sourceSha={sourceGitRef}
repoMetadata={repoMetadata} targetSha={targetGitRef}
emptyTitle={getString('compareEmptyDiffTitle')} handleRefresh={()=>{}} // TODO: when to refresh
emptyMessage={getString('compareEmptyDiffMessage')} />
/>
<ResourceListingPagination response={response} page={page} setPage={setPage} />
</Container>
)
}, },
{ {
id: 'diff', id: 'diff',
@ -292,11 +246,22 @@ export default function Compare() {
<TabTitleWithCount <TabTitleWithCount
icon={CodeIcon.File} icon={CodeIcon.File}
title={getString('filesChanged')} title={getString('filesChanged')}
count={diffs?.length || 0} count={data?.files_changed || 0}
padding={{ left: 'medium' }} padding={{ left: 'medium' }}
/> />
), ),
panel: ChangesTab panel:
<TabContentWrapper loading={loading} error={error} onRetry={()=>{}} className={css.changesContainer}>
<Changes
readOnly
repoMetadata={repoMetadata}
targetRef={targetGitRef}
sourceRef={sourceGitRef}
emptyTitle={getString('noChanges')}
emptyMessage={getString('noChangesCompare')}
onCommentUpdate={noop}
/>
</TabContentWrapper>
} }
]} ]}
/> />

View File

@ -0,0 +1,58 @@
import React from 'react'
import { useGet } from 'restful-react'
import type { TypesCommit } from 'services/code'
import type { GitInfoProps } from 'utils/GitUtils'
import { voidFn, LIST_FETCHING_LIMIT } from 'utils/Utils'
import { usePageIndex } from 'hooks/usePageIndex'
import { useStrings } from 'framework/strings'
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
import { CommitsView } from 'components/CommitsView/CommitsView'
import { TabContentWrapper } from 'components/TabContentWrapper/TabContentWrapper'
interface CommitProps extends Pick<GitInfoProps, 'repoMetadata'> {
sourceSha? :string
targetSha? :string
handleRefresh: () => void
}
export const CompareCommits: React.FC<CommitProps> = ({
repoMetadata,
sourceSha,
targetSha,
handleRefresh
}) => {
const limit = LIST_FETCHING_LIMIT
const [page, setPage] = usePageIndex()
const { getString } = useStrings()
const {
data,
error,
loading,
refetch,
response
} = useGet<{
commits: TypesCommit[]
}>({
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
queryParams: {
limit,
page,
git_ref: sourceSha,
after: targetSha
},
lazy: !repoMetadata
})
return (
<TabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}>
<CommitsView
commits={data?.commits || []}
repoMetadata={repoMetadata}
emptyTitle={getString('compareEmptyDiffTitle')}
emptyMessage={getString('compareEmptyDiffMessage')}
handleRefresh={voidFn(handleRefresh)}
/>
<ResourceListingPagination response={response} page={page} setPage={setPage} />
</TabContentWrapper>
)
}

View File

@ -226,8 +226,8 @@ export default function PullRequest() {
repoMetadata={repoMetadata as TypesRepository} repoMetadata={repoMetadata as TypesRepository}
pullRequestMetadata={prData as TypesPullReq} pullRequestMetadata={prData as TypesPullReq}
defaultCommitRange={compact(commitSHA?.split(/~1\.\.\.|\.\.\./g))} defaultCommitRange={compact(commitSHA?.split(/~1\.\.\.|\.\.\./g))}
targetRef={prData?.target_branch} targetRef={prData?.merge_base_sha}
sourceRef={prData?.source_branch} sourceRef={prData?.source_sha}
emptyTitle={getString('noChanges')} emptyTitle={getString('noChanges')}
emptyMessage={getString('noChangesPR')} emptyMessage={getString('noChangesPR')}
onCommentUpdate={voidFn(refetchPullRequest)} onCommentUpdate={voidFn(refetchPullRequest)}

View File

@ -24,18 +24,20 @@ export const PullRequestCommits: React.FC<CommitProps> = ({
const [page, setPage] = usePageIndex() const [page, setPage] = usePageIndex()
const { getString } = useStrings() const { getString } = useStrings()
const { const {
data: commits, data,
error, error,
loading, loading,
refetch, refetch,
response response
} = useGet<TypesCommit[]>({ } = useGet<{
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestMetadata.number}/commits`, commits: TypesCommit[]
}>({
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
queryParams: { queryParams: {
limit, limit,
page, page,
git_ref: pullRequestMetadata.source_branch, git_ref: pullRequestMetadata.source_sha,
after: pullRequestMetadata.target_branch after: pullRequestMetadata.merge_base_sha
}, },
lazy: !repoMetadata lazy: !repoMetadata
}) })
@ -43,7 +45,7 @@ export const PullRequestCommits: React.FC<CommitProps> = ({
return ( return (
<PullRequestTabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}> <PullRequestTabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}>
<CommitsView <CommitsView
commits={commits} commits={data?.commits || []}
repoMetadata={repoMetadata} repoMetadata={repoMetadata}
emptyTitle={getString('noCommits')} emptyTitle={getString('noCommits')}
emptyMessage={getString('noCommitsPR')} emptyMessage={getString('noCommitsPR')}

View File

@ -530,6 +530,7 @@ export interface TypesIdentity {
export interface TypesListCommitResponse { export interface TypesListCommitResponse {
commits?: TypesCommit[] | null commits?: TypesCommit[] | null
rename_details?: TypesRenameDetails[] | null rename_details?: TypesRenameDetails[] | null
total_commits?: number
} }
export interface TypesMembershipSpace { export interface TypesMembershipSpace {

File diff suppressed because it is too large Load Diff