package commands import ( "fmt" "os" "path" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/osfs" "github.com/go-git/go-git/v5" gitcfg "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing/cache" "github.com/go-git/go-git/v5/storage/filesystem" ) type TestSetupPaths struct { baseTestDirectory string baseTestRepository string } func checkErrorDuringPreparation(err error) { if err != nil { fmt.Printf("Cannot prepare a temporary directory for testing! %v ", err.Error()) os.Exit(2) } } func createRepositoryForTest() string { systemTMPDirectoryWithTestPath := fmt.Sprintf("%v/grmTest", os.TempDir()) if _, ok := os.Stat(systemTMPDirectoryWithTestPath); ok != nil { err := os.Mkdir(systemTMPDirectoryWithTestPath, 0777) checkErrorDuringPreparation(err) } temporaryDirPath, err := os.MkdirTemp(systemTMPDirectoryWithTestPath, "*") checkErrorDuringPreparation(err) return temporaryDirPath } // prepareRepositoryDirectories - prepare directories for file (rootRepositoryDirectory) and git metadata (gitMetadataDirectory) func prepareRepositoryDirectories(dirName string) (billy.Filesystem, billy.Filesystem) { rootRepositoryDirectory := osfs.New(dirName) gitMetadataDirectory, err := rootRepositoryDirectory.Chroot(".git") checkErrorDuringPreparation(err) return rootRepositoryDirectory, gitMetadataDirectory } func prepareBasicRepository() TestSetupPaths { temporaryDirPath := createRepositoryForTest() // Create an interface of abstraction over filesystem to provide tests over multiple systems // baseTestsDirectory - provides to main directory where new directories might be created baseTestsDirectory := osfs.New(temporaryDirPath) rootRepositoryDirectory, gitMetadataDirectory := prepareRepositoryDirectories(baseTestsDirectory.Root() + "/base_repository") repository, err := git.Init(filesystem.NewStorage( gitMetadataDirectory, cache.NewObjectLRUDefault()), rootRepositoryDirectory, ) checkErrorDuringPreparation(err) testFile, err := rootRepositoryDirectory.Create("TestFile.txt") checkErrorDuringPreparation(err) _, err = testFile.Write([]byte("foo-conent")) checkErrorDuringPreparation(err) repositoryWorkTree, err := repository.Worktree() checkErrorDuringPreparation(err) _, err = repositoryWorkTree.Add(testFile.Name()) checkErrorDuringPreparation(err) _, err = repositoryWorkTree.Commit("First commit", &git.CommitOptions{}) checkErrorDuringPreparation(err) return TestSetupPaths{ baseTestDirectory: baseTestsDirectory.Root(), baseTestRepository: rootRepositoryDirectory.Root(), } } func makeCommit(wk *git.Worktree, commitMessage string) { _, err := wk.Commit(commitMessage, &git.CommitOptions{}) checkErrorDuringPreparation(err) } // createAndCloneRepository - create sub-repository with cloned base repository required to verify sync command func createAndCloneRepository(repositoryName string, paths TestSetupPaths) *git.Repository { baseGitRepository, gitMetadataDirectory := prepareRepositoryDirectories( path.Join(paths.baseTestDirectory, repositoryName), ) storageForSubRepository := filesystem.NewStorage(gitMetadataDirectory, cache.NewObjectLRUDefault()) fakeLocalRepository, err := git.Clone(storageForSubRepository, baseGitRepository, &git.CloneOptions{ URL: paths.baseTestRepository, }) checkErrorDuringPreparation(err) return fakeLocalRepository } func addLocalRepositoryAsAFakeRemoteRepository(repository *git.Repository, baseTestRepositoryPath string) error { _, err := repository.CreateRemote(&gitcfg.RemoteConfig{ Name: "subremote", URLs: []string{baseTestRepositoryPath}, }) if err != nil { return err } return repository.Fetch(&git.FetchOptions{ RemoteName: "subremote", }) }