github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/commit_info_test.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  package git
     7  
     8  import (
     9  	"context"
    10  	"os"
    11  	"path/filepath"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/gitbundle/modules/util"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  const (
    21  	testReposDir = "tests/repos/"
    22  )
    23  
    24  func cloneRepo(url, name string) (string, error) {
    25  	repoDir, err := os.MkdirTemp("", name)
    26  	if err != nil {
    27  		return "", err
    28  	}
    29  	if err := Clone(DefaultContext, url, repoDir, CloneRepoOptions{
    30  		Mirror:  false,
    31  		Bare:    false,
    32  		Quiet:   true,
    33  		Timeout: 5 * time.Minute,
    34  	}); err != nil {
    35  		_ = util.RemoveAll(repoDir)
    36  		return "", err
    37  	}
    38  	return repoDir, nil
    39  }
    40  
    41  func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
    42  	// these test case are specific to the repo1 test repo
    43  	testCases := []struct {
    44  		CommitID           string
    45  		Path               string
    46  		ExpectedIDs        map[string]string
    47  		ExpectedTreeCommit string
    48  	}{
    49  		{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
    50  			"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
    51  			"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
    52  		}, "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2"},
    53  		{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
    54  			"file1.txt":   "2839944139e0de9737a044f78b0e4b40d989a9e3",
    55  			"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
    56  		}, "2839944139e0de9737a044f78b0e4b40d989a9e3"},
    57  		{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
    58  			"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
    59  		}, "5c80b0245c1c6f8343fa418ec374b13b5d4ee658"},
    60  		{"feaf4ba6bc635fec442f46ddd4512416ec43c2c2", "", map[string]string{
    61  			"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
    62  			"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
    63  			"foo":       "37991dec2c8e592043f47155ce4808d4580f9123",
    64  		}, "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"},
    65  	}
    66  	for _, testCase := range testCases {
    67  		commit, err := repo1.GetCommit(testCase.CommitID)
    68  		if err != nil {
    69  			assert.NoError(t, err, "Unable to get commit: %s from testcase due to error: %v", testCase.CommitID, err)
    70  			// no point trying to do anything else for this test.
    71  			continue
    72  		}
    73  		assert.NotNil(t, commit)
    74  		assert.NotNil(t, commit.Tree)
    75  		assert.NotNil(t, commit.Tree.repo)
    76  
    77  		tree, err := commit.Tree.SubTree(testCase.Path)
    78  		if err != nil {
    79  			assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
    80  			// no point trying to do anything else for this test.
    81  			continue
    82  		}
    83  
    84  		assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
    85  		assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
    86  
    87  		entries, err := tree.ListEntries()
    88  		if err != nil {
    89  			assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
    90  			// no point trying to do anything else for this test.
    91  			continue
    92  		}
    93  
    94  		// FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain.
    95  		commitsInfo, treeCommit, err := entries.GetCommitsInfo(context.TODO(), commit, testCase.Path, nil)
    96  		assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
    97  		if err != nil {
    98  			t.FailNow()
    99  		}
   100  		assert.Equal(t, testCase.ExpectedTreeCommit, treeCommit.ID.String())
   101  		assert.Len(t, commitsInfo, len(testCase.ExpectedIDs))
   102  		for _, commitInfo := range commitsInfo {
   103  			entry := commitInfo.Entry
   104  			commit := commitInfo.Commit
   105  			expectedID, ok := testCase.ExpectedIDs[entry.Name()]
   106  			if !assert.True(t, ok) {
   107  				continue
   108  			}
   109  			assert.Equal(t, expectedID, commit.ID.String())
   110  		}
   111  	}
   112  }
   113  
   114  func TestEntries_GetCommitsInfo(t *testing.T) {
   115  	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
   116  	bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path)
   117  	assert.NoError(t, err)
   118  	defer bareRepo1.Close()
   119  
   120  	testGetCommitsInfo(t, bareRepo1)
   121  
   122  	clonedPath, err := cloneRepo(bareRepo1Path, "repo1_TestEntries_GetCommitsInfo")
   123  	if err != nil {
   124  		assert.NoError(t, err)
   125  	}
   126  	defer util.RemoveAll(clonedPath)
   127  	clonedRepo1, err := openRepositoryWithDefaultContext(clonedPath)
   128  	if err != nil {
   129  		assert.NoError(t, err)
   130  	}
   131  	defer clonedRepo1.Close()
   132  
   133  	testGetCommitsInfo(t, clonedRepo1)
   134  }
   135  
   136  func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
   137  	type benchmarkType struct {
   138  		url  string
   139  		name string
   140  	}
   141  
   142  	benchmarks := []benchmarkType{
   143  		{url: "https://github.com/go-gitea/gitea.git", name: "gitea"},
   144  		{url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"},
   145  		{url: "https://github.com/moby/moby.git", name: "moby"},
   146  		{url: "https://github.com/golang/go.git", name: "go"},
   147  		{url: "https://github.com/torvalds/linux.git", name: "linux"},
   148  	}
   149  
   150  	doBenchmark := func(benchmark benchmarkType) {
   151  		var commit *Commit
   152  		var entries Entries
   153  		var repo *Repository
   154  		repoPath, err := cloneRepo(benchmark.url, benchmark.name)
   155  		if err != nil {
   156  			b.Fatal(err)
   157  		}
   158  		defer util.RemoveAll(repoPath)
   159  
   160  		if repo, err = openRepositoryWithDefaultContext(repoPath); err != nil {
   161  			b.Fatal(err)
   162  		}
   163  		defer repo.Close()
   164  
   165  		if commit, err = repo.GetBranchCommit("master"); err != nil {
   166  			b.Fatal(err)
   167  		} else if entries, err = commit.Tree.ListEntries(); err != nil {
   168  			b.Fatal(err)
   169  		}
   170  		entries.Sort()
   171  		b.ResetTimer()
   172  		b.Run(benchmark.name, func(b *testing.B) {
   173  			for i := 0; i < b.N; i++ {
   174  				_, _, err := entries.GetCommitsInfo(context.Background(), commit, "", nil)
   175  				if err != nil {
   176  					b.Fatal(err)
   177  				}
   178  			}
   179  		})
   180  	}
   181  
   182  	for _, benchmark := range benchmarks {
   183  		doBenchmark(benchmark)
   184  	}
   185  }