2020-12-17 17:00:47 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2021-08-24 19:47:09 +03:00
//go:build !gogit
2020-12-17 17:00:47 +03:00
package git
import (
"bufio"
2021-02-19 03:40:17 +03:00
"errors"
2020-12-17 17:00:47 +03:00
"io"
"strings"
2021-06-25 19:54:08 +03:00
"code.gitea.io/gitea/modules/log"
2020-12-17 17:00:47 +03:00
)
// ResolveReference resolves a name to a reference
func ( repo * Repository ) ResolveReference ( name string ) ( string , error ) {
2022-10-23 17:44:45 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "show-ref" , "--hash" ) . AddDynamicArguments ( name ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2020-12-17 17:00:47 +03:00
if err != nil {
if strings . Contains ( err . Error ( ) , "not a valid ref" ) {
return "" , ErrNotExist { name , "" }
}
return "" , err
}
stdout = strings . TrimSpace ( stdout )
if stdout == "" {
return "" , ErrNotExist { name , "" }
}
return stdout , nil
}
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
func ( repo * Repository ) GetRefCommitID ( name string ) ( string , error ) {
2021-11-30 23:06:32 +03:00
wr , rd , cancel := repo . CatFileBatchCheck ( repo . Ctx )
2021-05-10 04:27:03 +03:00
defer cancel ( )
2021-12-16 22:01:14 +03:00
_ , err := wr . Write ( [ ] byte ( name + "\n" ) )
if err != nil {
return "" , err
}
2021-05-10 04:27:03 +03:00
shaBs , _ , _ , err := ReadBatchLine ( rd )
if IsErrNotExist ( err ) {
return "" , ErrNotExist { name , "" }
2020-12-17 17:00:47 +03:00
}
2021-05-10 04:27:03 +03:00
return string ( shaBs ) , nil
2020-12-17 17:00:47 +03:00
}
2021-12-23 16:44:00 +03:00
// SetReference sets the commit ID string of given reference (e.g. branch or tag).
func ( repo * Repository ) SetReference ( name , commitID string ) error {
2022-10-23 17:44:45 +03:00
_ , _ , err := NewCommand ( repo . Ctx , "update-ref" ) . AddDynamicArguments ( name , commitID ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2021-12-23 16:44:00 +03:00
return err
}
// RemoveReference removes the given reference (e.g. branch or tag).
func ( repo * Repository ) RemoveReference ( name string ) error {
2022-10-23 17:44:45 +03:00
_ , _ , err := NewCommand ( repo . Ctx , "update-ref" , "--no-deref" , "-d" ) . AddDynamicArguments ( name ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2021-12-23 16:44:00 +03:00
return err
}
2020-12-17 17:00:47 +03:00
// IsCommitExist returns true if given commit exists in current repository.
func ( repo * Repository ) IsCommitExist ( name string ) bool {
2022-10-23 17:44:45 +03:00
_ , _ , err := NewCommand ( repo . Ctx , "cat-file" , "-e" ) . AddDynamicArguments ( name ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2020-12-17 17:00:47 +03:00
return err == nil
}
func ( repo * Repository ) getCommit ( id SHA1 ) ( * Commit , error ) {
2021-11-30 23:06:32 +03:00
wr , rd , cancel := repo . CatFileBatch ( repo . Ctx )
2021-05-10 04:27:03 +03:00
defer cancel ( )
2020-12-17 17:00:47 +03:00
2021-05-10 04:27:03 +03:00
_ , _ = wr . Write ( [ ] byte ( id . String ( ) + "\n" ) )
2021-05-02 04:16:08 +03:00
2021-05-10 04:27:03 +03:00
return repo . getCommitFromBatchReader ( rd , id )
2021-05-02 04:16:08 +03:00
}
2021-05-10 04:27:03 +03:00
func ( repo * Repository ) getCommitFromBatchReader ( rd * bufio . Reader , id SHA1 ) ( * Commit , error ) {
_ , typ , size , err := ReadBatchLine ( rd )
2020-12-17 17:00:47 +03:00
if err != nil {
2021-05-10 04:27:03 +03:00
if errors . Is ( err , io . EOF ) || IsErrNotExist ( err ) {
2021-02-19 03:40:17 +03:00
return nil , ErrNotExist { ID : id . String ( ) }
}
2020-12-17 17:00:47 +03:00
return nil , err
}
switch typ {
2021-02-19 03:40:17 +03:00
case "missing" :
return nil , ErrNotExist { ID : id . String ( ) }
2020-12-17 17:00:47 +03:00
case "tag" :
// then we need to parse the tag
// and load the commit
2021-09-22 08:38:34 +03:00
data , err := io . ReadAll ( io . LimitReader ( rd , size ) )
2021-05-10 04:27:03 +03:00
if err != nil {
return nil , err
}
_ , err = rd . Discard ( 1 )
2020-12-17 17:00:47 +03:00
if err != nil {
return nil , err
}
tag , err := parseTagData ( data )
if err != nil {
return nil , err
}
2022-01-12 23:37:46 +03:00
commit , err := tag . Commit ( repo )
2020-12-17 17:00:47 +03:00
if err != nil {
return nil , err
}
commit . CommitMessage = strings . TrimSpace ( tag . Message )
commit . Author = tag . Tagger
commit . Signature = tag . Signature
return commit , nil
case "commit" :
2021-05-10 04:27:03 +03:00
commit , err := CommitFromReader ( repo , id , io . LimitReader ( rd , size ) )
if err != nil {
return nil , err
}
_ , err = rd . Discard ( 1 )
if err != nil {
return nil , err
}
return commit , nil
2020-12-17 17:00:47 +03:00
default :
2021-06-25 19:54:08 +03:00
log . Debug ( "Unknown typ: %s" , typ )
2021-05-10 04:27:03 +03:00
_ , err = rd . Discard ( int ( size ) + 1 )
if err != nil {
return nil , err
}
2020-12-17 17:00:47 +03:00
return nil , ErrNotExist {
ID : id . String ( ) ,
}
}
}
2021-05-10 04:27:03 +03:00
// ConvertToSHA1 returns a Hash object from a potential ID string
func ( repo * Repository ) ConvertToSHA1 ( commitID string ) ( SHA1 , error ) {
2022-09-04 13:47:56 +03:00
if len ( commitID ) == 40 && IsValidSHAPattern ( commitID ) {
2021-05-10 04:27:03 +03:00
sha1 , err := NewIDFromString ( commitID )
if err == nil {
return sha1 , nil
}
}
2021-11-30 23:06:32 +03:00
wr , rd , cancel := repo . CatFileBatchCheck ( repo . Ctx )
2021-05-10 04:27:03 +03:00
defer cancel ( )
_ , err := wr . Write ( [ ] byte ( commitID + "\n" ) )
if err != nil {
return SHA1 { } , err
}
sha , _ , _ , err := ReadBatchLine ( rd )
if err != nil {
if IsErrNotExist ( err ) {
return SHA1 { } , ErrNotExist { commitID , "" }
}
return SHA1 { } , err
}
return MustIDFromString ( string ( sha ) ) , nil
}