github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/repo_commit_nogogit.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  //go:build !gogit
     7  
     8  package git
     9  
    10  import (
    11  	"bufio"
    12  	"errors"
    13  	"io"
    14  	"strings"
    15  
    16  	"github.com/gitbundle/modules/log"
    17  )
    18  
    19  // ResolveReference resolves a name to a reference
    20  func (repo *Repository) ResolveReference(name string) (string, error) {
    21  	stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--hash", name).RunStdString(&RunOpts{Dir: repo.Path})
    22  	if err != nil {
    23  		if strings.Contains(err.Error(), "not a valid ref") {
    24  			return "", ErrNotExist{name, ""}
    25  		}
    26  		return "", err
    27  	}
    28  	stdout = strings.TrimSpace(stdout)
    29  	if stdout == "" {
    30  		return "", ErrNotExist{name, ""}
    31  	}
    32  
    33  	return stdout, nil
    34  }
    35  
    36  // GetRefCommitID returns the last commit ID string of given reference (branch or tag).
    37  func (repo *Repository) GetRefCommitID(name string) (string, error) {
    38  	wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
    39  	defer cancel()
    40  	_, err := wr.Write([]byte(name + "\n"))
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  	shaBs, _, _, err := ReadBatchLine(rd)
    45  	if IsErrNotExist(err) {
    46  		return "", ErrNotExist{name, ""}
    47  	}
    48  
    49  	return string(shaBs), nil
    50  }
    51  
    52  // SetReference sets the commit ID string of given reference (e.g. branch or tag).
    53  func (repo *Repository) SetReference(name, commitID string) error {
    54  	_, _, err := NewCommand(repo.Ctx, "update-ref", name, commitID).RunStdString(&RunOpts{Dir: repo.Path})
    55  	return err
    56  }
    57  
    58  // RemoveReference removes the given reference (e.g. branch or tag).
    59  func (repo *Repository) RemoveReference(name string) error {
    60  	_, _, err := NewCommand(repo.Ctx, "update-ref", "--no-deref", "-d", name).RunStdString(&RunOpts{Dir: repo.Path})
    61  	return err
    62  }
    63  
    64  // IsCommitExist returns true if given commit exists in current repository.
    65  func (repo *Repository) IsCommitExist(name string) bool {
    66  	_, _, err := NewCommand(repo.Ctx, "cat-file", "-e", name).RunStdString(&RunOpts{Dir: repo.Path})
    67  	return err == nil
    68  }
    69  
    70  func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
    71  	wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
    72  	defer cancel()
    73  
    74  	_, _ = wr.Write([]byte(id.String() + "\n"))
    75  
    76  	return repo.getCommitFromBatchReader(rd, id)
    77  }
    78  
    79  func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Commit, error) {
    80  	_, typ, size, err := ReadBatchLine(rd)
    81  	if err != nil {
    82  		if errors.Is(err, io.EOF) || IsErrNotExist(err) {
    83  			return nil, ErrNotExist{ID: id.String()}
    84  		}
    85  		return nil, err
    86  	}
    87  
    88  	switch typ {
    89  	case "missing":
    90  		return nil, ErrNotExist{ID: id.String()}
    91  	case "tag":
    92  		// then we need to parse the tag
    93  		// and load the commit
    94  		data, err := io.ReadAll(io.LimitReader(rd, size))
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		_, err = rd.Discard(1)
    99  		if err != nil {
   100  			return nil, err
   101  		}
   102  		tag, err := parseTagData(data)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  
   107  		commit, err := tag.Commit(repo)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  
   112  		commit.CommitMessage = strings.TrimSpace(tag.Message)
   113  		commit.Author = tag.Tagger
   114  		commit.Signature = tag.Signature
   115  
   116  		return commit, nil
   117  	case "commit":
   118  		commit, err := CommitFromReader(repo, id, io.LimitReader(rd, size))
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  		_, err = rd.Discard(1)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  
   127  		return commit, nil
   128  	default:
   129  		log.Debug("Unknown typ: %s", typ)
   130  		_, err = rd.Discard(int(size) + 1)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  		return nil, ErrNotExist{
   135  			ID: id.String(),
   136  		}
   137  	}
   138  }
   139  
   140  // ConvertToSHA1 returns a Hash object from a potential ID string
   141  func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
   142  	if len(commitID) == 40 && SHAPattern.MatchString(commitID) {
   143  		sha1, err := NewIDFromString(commitID)
   144  		if err == nil {
   145  			return sha1, nil
   146  		}
   147  	}
   148  
   149  	wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
   150  	defer cancel()
   151  	_, err := wr.Write([]byte(commitID + "\n"))
   152  	if err != nil {
   153  		return SHA1{}, err
   154  	}
   155  	sha, _, _, err := ReadBatchLine(rd)
   156  	if err != nil {
   157  		if IsErrNotExist(err) {
   158  			return SHA1{}, ErrNotExist{commitID, ""}
   159  		}
   160  		return SHA1{}, err
   161  	}
   162  
   163  	return MustIDFromString(string(sha)), nil
   164  }