gittest

package
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2024 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultBranch contains the name of the default branch used when
	// initializing the test repository
	DefaultBranch = "main"

	// DefaultOrigin contains the name of the default origin that connects
	// the local repository back to its remote counterpart
	DefaultOrigin = "origin"

	// DefaultRemoteBranch contains the name of the default branch when
	// initializing the remote bare repository
	DefaultRemoteBranch = "origin/main"

	// DefaultRemoteBranchHEAD is a remote tracking branch that points at
	// the default branch of the repository
	DefaultRemoteBranchAlias = "origin/HEAD"

	// DefaultAuthorName contains the author name written to local git
	// config when initializing the test repository
	DefaultAuthorName = "batman"

	// DefaultAuthorEmail contains the author email written to local git
	// config when initializing the test repository
	DefaultAuthorEmail = "batman@dc.com"

	// DefaultAuthorLog contains the default git representation of an author
	// and can be used for matching against entries within a git log
	DefaultAuthorLog = "batman <batman@dc.com>"

	// InitialCommit contains the first commit message used to initialize
	// the test repository
	InitialCommit = "initialized repository"

	// BareRepositoryName the name of the bare repository, used as the
	// remote for all testing
	BareRepositoryName = "test.git"

	// ClonedRepositoryName the name of the repository (working directory)
	// after cloning the bare repository
	ClonedRepositoryName = "test"

	// FileContent is written to any file generated by the [WithFiles] and [WithStagedFiles]
	// options. Grabbed from: https://loremipsum.io/
	FileContent = "" /* 445-byte string literal not displayed */

)

Variables

This section is empty.

Functions

func Blob added in v0.7.0

func Blob(t *testing.T, path string) string

Blob retrieves the string representation of a blob within the git tree. The tree is scanned using the provided path to obtain the blob reference. The content is retrieved using this command:

git show -s <ref>

func Branches added in v0.3.0

func Branches(t *testing.T) []string

Branches returns a list of all local branches associated with the current repository. Raw output is parsed from this command:

git branch --list --format='%(refname:short)'

func Checkout added in v0.2.0

func Checkout(t *testing.T, object string) string

Checkout will update the state of the repository (working directory) by updating files in the tree to a specific point in time. Object can be any one of the following:

  • Commit reference (long or abbreviated hash)
  • Tag reference
  • Branch name

Be warned, checking out a tag or commit reference will cause a detached HEAD for the current repository. Raw output is returned from this command:

git checkout '<object>'

func Commit

func Commit(t *testing.T, message string)

Commit a snapshot of all changes within the current repository (working directory) without pushing it to the remote. The commit will be associated with the provided message. The following git command is executed:

git commit -m '<message>'

func CommitEmpty added in v0.6.0

func CommitEmpty(t *testing.T, message string)

CommitEmpty allows a snapshot of the current repository (working directory) to be created without any changes. The commit will be associated with the provided message. The following git command is executed:

git commit --allow-empty -m '<message>'

func CommitEmptyWithAuthor added in v0.6.0

func CommitEmptyWithAuthor(t *testing.T, name, email, message string)

CommitEmptyWithAuthor allows a snapshot of the current repository (working directory) to be created without any changes. The commit will be associated with the provided message and author. The following git command is executed:

git commit --allow-empty --author='name <email>' -m '<message>'

func CommitWithAuthor added in v0.6.0

func CommitWithAuthor(t *testing.T, name, email, message string)

CommitWithAuthor a snapshot of all changes within the current repository (working directory) without pushing it to the remote. The commit will be associated with the provided message and author. The following git command is executed:

git commit --author='name <email>' -m '<message>'

func ConfigSet added in v0.5.0

func ConfigSet(t *testing.T, pairs ...string)

ConfigSet will set any number of local git config items for the current repository. Input must contain an even number of pairs. The following git command is executed for each config pair:

git config --add <path> '<value>'

func Exec

func Exec(t *testing.T, cmd string) (string, error)

Exec will execute any given git command and return the raw output and error from the underlying git client

func InitRepository

func InitRepository(t *testing.T, opts ...RepositoryOption)

InitRepository will attempt to initialize a test repository capable of supporting any git operation. Options can be provided to customize the initialization process, changing the default configuration used.

It is important to note, that options will be executed within a particular order:

  1. Log history will be imported (local and remote are in sync)
  2. A shallow clone is made at the required clone depth
  3. Remote log history will be imported, creating a delta between the current repository (working directory) and the remote
  4. All local empty commits are made without pushing back to the remote
  5. All named files will be created and either staged or committed if required
  6. Overwrites existing files with user-defined content.

Repository creation consists of two phases. First, a bare repository is initialized, before being cloned locally. This ensures a fully working remote. Without customization (options), the test repository will consist of single commit:

initialized repository

func MustExec added in v0.2.0

func MustExec(t *testing.T, cmd string) string

MustExec will execute any given git command, requiring no failure. Any raw output will be returned from the underlying git client

func ObjectRef added in v0.6.0

func ObjectRef(t *testing.T, path string) string

ObjectRef scans the tree of the current repository for a an object identified by the provided file path. If the object exists within a sub-directory, the scan will recursively search sub-trees until the path is resolved.

The object ref is parsed from this command:

git ls-tree <ref>

func PorcelainStatus

func PorcelainStatus(t *testing.T) []string

PorcelainStatus returns a snapshot of the current status of a repository (working directory) in an easy to parse format. Raw output is parsed from the git command:

git status --porcelain

func Remote added in v0.2.0

func Remote(t *testing.T) string

Remote will retrieve the URL of the remote (typically origin) configured for the current repository (working directory). To prevent issues due to OS dependent separators, the raw URL will be converted to use the '/' separator which is compatible across OS when using the git client.

Remote is queried using this command:

git ls-remote --get-url

func RemoteBranches added in v0.3.0

func RemoteBranches(t *testing.T) []string

RemoteBranches returns a list of all branches that have been pushed to the remote origin of the current repository. Remote branch names are prefixed with the default origin of the remote:

origin/main
origin/branch

Raw output is parsed from this command:

git branch --list --remotes --format='%(refname:short)'

func RemoteTags

func RemoteTags(t *testing.T) []string

RemoteTags returns a list of all tags that have been pushed to the remote origin of the current repository. Raw output is returned from the git command:

git ls-remote --tags

func Show

func Show(t *testing.T, object string) string

Show will display information about a specific git object. The output will vary based on the type of object being shown:

  • For commits it shows the log message and textual diff
  • For tags, it shows the tag message and the referenced objects
  • For trees, it shows the names
  • For plain blobs, it shows the plain contents

Raw output is returned from this command:

git show '<object>'

func ShowBranch added in v0.3.0

func ShowBranch(t *testing.T) string

ShowBranch will retrieve the name of the current branch. Raw output is returned from this command:

git branch --show-current

func StageAll added in v0.7.0

func StageAll(t *testing.T)

StageAll will stage all changes to new and existing files, respecting the contents of the .gitignore file. The following git command is executed:

git add -A

func StageFile

func StageFile(t *testing.T, path string)

StageFile will attempt to use the provided path to stage a file that has been modified. The following git command is executed:

git add '<path>'

func StagedFile added in v0.7.0

func StagedFile(t *testing.T, path, content string)

StagedFile generates a temporary file with the given content and ensures it is staged. A utility method that calls TempFile followed by StageFile

func Tag added in v0.6.0

func Tag(t *testing.T, tag string)

Tag creates a lightweight tag that is only tracked locally and will not have been pushed back to the remote repository. The following git command is executed:

git tag '<tag>'

func TagAnnotated added in v0.6.0

func TagAnnotated(t *testing.T, tag, msg string)

TagAnnotated creates an annotated tag that is only tracked locally and will not have been pushed back to the remote repository. An annotated tag is tracked as a full git object within the index, compared to a lightweight tag. The following git command is executed:

git tag -a '<tag>' -m '<msg>'

func TagRemote added in v0.7.0

func TagRemote(t *testing.T, tag string)

TagRemote creates lightweight tag that is only tracked at the remote. This is achieved by deleting the local reference to the tag after it has been pushed. The following git commands are executed:

git tag '<tag>'
git push origin '<tag>'
git tag -d '<tag>'

func Tags

func Tags(t *testing.T) []string

Tags returns a list of all local tags associated with the current repository. Raw output is returned from the git command:

git for-each-ref refs/tags --format='%(refname:short)'

func TempFile added in v0.6.0

func TempFile(t *testing.T, path, content string)

TempFile generates a temporary file with the given content at the provided location within the file system. All directories will be created with permissions of 0750 (drwxr-xr-x), and the file created with permissions of 0640 (-rw-r--r--)

func WorkingDirectory added in v0.4.0

func WorkingDirectory(t *testing.T) string

WorkingDirectory returns the working directory (root) of the current repository

Raw output is parsed from this command:

git rev-parse --show-toplevel

Types

type CommitDetails added in v0.3.0

type CommitDetails struct {
	Hash        string
	AbbrevHash  string
	AuthorName  string
	AuthorEmail string
	Message     string
}

CommitDetails contains details about a specific git commit

func LastCommit

func LastCommit(t *testing.T) CommitDetails

LastCommit returns the last commit from the git log of the current repository. Raw output is parsed from the git command:

git log -n1

type LogEntry

type LogEntry struct {
	// Hash contains the unique identifier associated with the commit
	Hash string

	// AbbrevHash contains the seven character abbreviated commit hash
	AbbrevHash string

	// Message contains the log message associated with the commit
	Message string

	// Tags contains all tag references that are associated
	// with the current commit
	Tags []string

	// Branches contains the name of all branches (local and remote)
	// that are associated with the current commit
	Branches []string

	// IsTrunk identifies if the current log entry has a reference
	// to the default branch
	IsTrunk bool

	// HeadPointerRef contains the name of the branch the HEAD of the
	// repository points to
	HeadPointerRef string
}

LogEntry represents a single log entry from the history of a git repository

func Log added in v0.3.0

func Log(t *testing.T) []LogEntry

Log returns the log history of a repository (working directory) as it currently exists on the default branch. Raw output is parsed from this command:

git log --pretty='format:> %H %d %s%+b%-N' main

func LogBetween added in v0.7.0

func LogBetween(t *testing.T, from, to string) []LogEntry

LogBetween returns the log history of a repository (working directory) between two references. Raw output is parsed from this command:

git log --pretty='format:> %%H %%d %%s%%+b%%-N' <from>..<to>

func ParseLog

func ParseLog(log string) []LogEntry

ParseLog will attempt to parse a log extract from a given repository into a series of commits, branches and tags. The log will be returned in the chronological order provided. The parser is designed to not error and parses each line with best endeavors. Multiple log formats are supported:

1. A condensed single line log format:

(HEAD -> new-feature, origin/new-feature) pass tests
write tests for new feature
(tag: 0.2.0, tag: v1, main, origin/main) feat: improve existing cli documentation
docs: create initial mkdocs material documentation
(tag: 0.1.0) feat: add secondary cli command to support filtering of results
feat: scaffold initial cli and add first command

This is the equivalent to the format produced using the git command:

git log --pretty='format:%d %s'

2. A multi-line commit format, which is denotoed with the presence of the prefix marker >. The parser will switch between parsing modes if it detects the existence of this marker on the first character of the provided log extract:

> (HEAD -> new-feature, origin/new-feature) pass tests
> write tests for new feature
> (tag: 0.2.0, tag: v1, main, origin/main) feat: improve existing cli documentation

This is the equivalent to the format produced using the git command:

git log --pretty='format:> %d %s%+b%-N'

3. A log containing an optional leading forty character hash. Can be used in conjunction with both single line and multi-line formats:

> b0d5429b967b9af0a0805fc2981b4420e10be38d (HEAD -> new-feature, origin/new-feature) pass tests
> 58d708cb071df97e2561903aadcd4129419e9631 write tests for new feature
> 4edd1a7e492aeeaf2a97ad57433e236bc72e1d93 (tag: 0.2.0, tag: v1, main, origin/main) feat: improve existing cli documentation

This is the equivalent to the format produced using the git command:

git log --pretty='format:> %H %d %s%+b%-N'

func RemoteLog added in v0.3.0

func RemoteLog(t *testing.T) []LogEntry

RemoteLog returns the log history of a repository (working directory) as it currently exists on the remote. Any local commits that are not pushed, will not appear within this log history. Raw output is parsed from this command:

git log --pretty='format:> %H %d %s%+b%-N' origin/main

type RepositoryOption

type RepositoryOption func(*repositoryOptions)

RepositoryOption provides a utility for setting repository options during initialization. A repository will always be created with sensible default values

func WithCloneDepth added in v0.2.0

func WithCloneDepth(depth int) RepositoryOption

WithCloneDepth ensures the repository will be cloned at a specific depth, effectively truncating the history to the required number of commits. The result will be a shallow repository

func WithCommittedFiles added in v0.7.0

func WithCommittedFiles(files ...string) RepositoryOption

WithCommittedFiles ensures the repository will be initialized with a given set of named files. Both relative and full file paths are supported. Each file will be generated using default data, and will be committed under a single commit 'include test files'

For example:

gittest.InitRepository(t, gittest.WithCommittedFiles("file1.txt", "file2.txt"))

This will result in a repository containing two committed files and no outstanding changes

func WithFileContent added in v0.7.0

func WithFileContent(pairs ...string) RepositoryOption

WithFileContent allows the default file content associated with files created through the WithFiles, WithCommittedFiles or WithStagedFiles options to be overwritten with user defined content. Input to this option is in the form of path and content pairs.

For example:

gittest.InitRepository(gittest.WithFiles("file1.txt", "file2.txt"),
	gittest.WithFileContent("file1.txt", "hello", "file2.txt", "world"))

Inspecting the contents of the files will output:

file1.txt => "hello"
file2.txt => "world"

Mismatched pairs will result in the final file in the list not being updated

func WithFiles

func WithFiles(files ...string) RepositoryOption

WithFiles ensures the repository will be initialized with a given set of named files. Both relative and full file paths are supported. Each file will be generated using default data, but will remain untracked by the repository.

For example:

gittest.InitRepository(t, gittest.WithFiles("file1.txt", "file2.txt"))

This will result in a repository containing two untracked files. Which can be verified by checking the git status:

$ git status --porcelain
?? file1.txt
?? file2.txt

func WithLocalCommits

func WithLocalCommits(commits ...string) RepositoryOption

WithLocalCommits ensures the repository will be initialized with a set of local empty commits, which will not have been pushed back to the remote

func WithLog

func WithLog(log string) RepositoryOption

WithLog ensures the repository will be initialized to a known state. The log can be used to create any number of tags and branches (both local and remote) at different commits within the repositories history. The HEAD pointer reference (HEAD -> <branch>) is supported and allows a repository to check out a branch after completing the import.

Given the following log extract:

(HEAD -> new-feature, origin/new-feature) pass tests
write tests for new feature
(main, origin/main) ci: add code security github workflow
(code-example-docs) chore: add example code snippets
(tag: 0.1.1, origin/parsing-tests) fix: parsing of multiple tags within log
(tag: 0.1.0) feat: parsing of multiple tags within log
chore: update existing project README

The repository would be initialized with the known state:

  • Tag '0.1.0' references commit 'feat: parsing of multiple tags within log'
  • Tag '0.1.1' references commit 'fix: parsing of multiple tags within log'
  • Remote branch 'parsing-tests' was branched from commit 'fix: parsing of multiple tags within log' and hasn't been checked out locally
  • Local branch 'code-example-docs' was branched from commit 'chore: add example code snippets' but has not been pushed to the remote
  • The default branch references commit 'ci: add code security github workflow'
  • Local branch 'new-feature' has been checked out will all commits being pushed back to the remote

The provided log is parsed using ParseLog and is based on the output of git command:

git log --pretty='format:%d %s'

func WithRemoteLog

func WithRemoteLog(log string) RepositoryOption

WithRemoteLog ensures the remote origin of the repository will be initialized to a known state. Ideal for simulating a delta between the current repository (working directory) and the remote. Use with caution, as this can result in conflicts.

Some typical scenarios for this option. Both require a git pull for synchronization.

1. Introducing a delta with the default branch:

(tag: 0.1.0, main, origin/main) feat: improve existing cli documentation
docs: create initial mkdocs material documentation

2. Introducing a delta for a new branch:

(HEAD -> new-branch, origin/new-branch) pass tests
write tests for new feature

The provided log is parsed using ParseLog and is based on the output of git command:

git log --pretty='format:%d %s'

func WithStagedFiles

func WithStagedFiles(files ...string) RepositoryOption

WithStagedFiles ensures the repository will be initialized with a given set of named files. Both relative and full file paths are supported. Each file will be generated using default data, and will be staged within the repository.

For example:

gittest.InitRepository(t, gittest.WithStagedFiles("file1.txt", "file2.txt"))

This will result in a repository containing two staged files. Which can be verified by checking the git status:

$ git status --porcelain
A  file1.txt
A  file2.txt

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL