// Code generated by mockery v0.0.0-dev. DO NOT EDIT.

package mocks

import (
	context "context"
	fs "io/fs"

	git "go.skia.org/infra/go/git"

	gitiles "go.skia.org/infra/go/gitiles"

	mock "github.com/stretchr/testify/mock"

	vcsinfo "go.skia.org/infra/go/vcsinfo"
)

// GitilesRepo is an autogenerated mock type for the GitilesRepo type
type GitilesRepo struct {
	mock.Mock
}

// Branches provides a mock function with given fields: ctx
func (_m *GitilesRepo) Branches(ctx context.Context) ([]*git.Branch, error) {
	ret := _m.Called(ctx)

	if len(ret) == 0 {
		panic("no return value specified for Branches")
	}

	var r0 []*git.Branch
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context) ([]*git.Branch, error)); ok {
		return rf(ctx)
	}
	if rf, ok := ret.Get(0).(func(context.Context) []*git.Branch); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*git.Branch)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Details provides a mock function with given fields: ctx, ref
func (_m *GitilesRepo) Details(ctx context.Context, ref string) (*vcsinfo.LongCommit, error) {
	ret := _m.Called(ctx, ref)

	if len(ret) == 0 {
		panic("no return value specified for Details")
	}

	var r0 *vcsinfo.LongCommit
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) (*vcsinfo.LongCommit, error)); ok {
		return rf(ctx, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) *vcsinfo.LongCommit); ok {
		r0 = rf(ctx, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*vcsinfo.LongCommit)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// DownloadFile provides a mock function with given fields: ctx, srcPath, dstPath
func (_m *GitilesRepo) DownloadFile(ctx context.Context, srcPath string, dstPath string) error {
	ret := _m.Called(ctx, srcPath, dstPath)

	if len(ret) == 0 {
		panic("no return value specified for DownloadFile")
	}

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
		r0 = rf(ctx, srcPath, dstPath)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// DownloadFileAtRef provides a mock function with given fields: ctx, srcPath, ref, dstPath
func (_m *GitilesRepo) DownloadFileAtRef(ctx context.Context, srcPath string, ref string, dstPath string) error {
	ret := _m.Called(ctx, srcPath, ref, dstPath)

	if len(ret) == 0 {
		panic("no return value specified for DownloadFileAtRef")
	}

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok {
		r0 = rf(ctx, srcPath, ref, dstPath)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// ListDir provides a mock function with given fields: ctx, dir
func (_m *GitilesRepo) ListDir(ctx context.Context, dir string) ([]fs.FileInfo, error) {
	ret := _m.Called(ctx, dir)

	if len(ret) == 0 {
		panic("no return value specified for ListDir")
	}

	var r0 []fs.FileInfo
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) ([]fs.FileInfo, error)); ok {
		return rf(ctx, dir)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) []fs.FileInfo); ok {
		r0 = rf(ctx, dir)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]fs.FileInfo)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, dir)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListDirAtRef provides a mock function with given fields: ctx, dir, ref
func (_m *GitilesRepo) ListDirAtRef(ctx context.Context, dir string, ref string) ([]fs.FileInfo, error) {
	ret := _m.Called(ctx, dir, ref)

	if len(ret) == 0 {
		panic("no return value specified for ListDirAtRef")
	}

	var r0 []fs.FileInfo
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) ([]fs.FileInfo, error)); ok {
		return rf(ctx, dir, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []fs.FileInfo); ok {
		r0 = rf(ctx, dir, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]fs.FileInfo)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, dir, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListFilesRecursive provides a mock function with given fields: ctx, dir
func (_m *GitilesRepo) ListFilesRecursive(ctx context.Context, dir string) ([]string, error) {
	ret := _m.Called(ctx, dir)

	if len(ret) == 0 {
		panic("no return value specified for ListFilesRecursive")
	}

	var r0 []string
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) ([]string, error)); ok {
		return rf(ctx, dir)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok {
		r0 = rf(ctx, dir)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]string)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, dir)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListFilesRecursiveAtRef provides a mock function with given fields: ctx, topDir, ref
func (_m *GitilesRepo) ListFilesRecursiveAtRef(ctx context.Context, topDir string, ref string) ([]string, error) {
	ret := _m.Called(ctx, topDir, ref)

	if len(ret) == 0 {
		panic("no return value specified for ListFilesRecursiveAtRef")
	}

	var r0 []string
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) ([]string, error)); ok {
		return rf(ctx, topDir, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []string); ok {
		r0 = rf(ctx, topDir, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]string)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, topDir, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Log provides a mock function with given fields: ctx, logExpr, opts
func (_m *GitilesRepo) Log(ctx context.Context, logExpr string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	if len(ret) == 0 {
		panic("no return value specified for Log")
	}

	var r0 []*vcsinfo.LongCommit
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error)); ok {
		return rf(ctx, logExpr, opts...)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, logExpr, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, logExpr, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// LogFirstParent provides a mock function with given fields: ctx, from, to, opts
func (_m *GitilesRepo) LogFirstParent(ctx context.Context, from string, to string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, from, to)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	if len(ret) == 0 {
		panic("no return value specified for LogFirstParent")
	}

	var r0 []*vcsinfo.LongCommit
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error)); ok {
		return rf(ctx, from, to, opts...)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, from, to, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, from, to, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// LogFn provides a mock function with given fields: ctx, logExpr, fn, opts
func (_m *GitilesRepo) LogFn(ctx context.Context, logExpr string, fn func(context.Context, *vcsinfo.LongCommit) error, opts ...gitiles.LogOption) error {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr, fn)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	if len(ret) == 0 {
		panic("no return value specified for LogFn")
	}

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, func(context.Context, *vcsinfo.LongCommit) error, ...gitiles.LogOption) error); ok {
		r0 = rf(ctx, logExpr, fn, opts...)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// LogFnBatch provides a mock function with given fields: ctx, logExpr, fn, opts
func (_m *GitilesRepo) LogFnBatch(ctx context.Context, logExpr string, fn func(context.Context, []*vcsinfo.LongCommit) error, opts ...gitiles.LogOption) error {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr, fn)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	if len(ret) == 0 {
		panic("no return value specified for LogFnBatch")
	}

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, func(context.Context, []*vcsinfo.LongCommit) error, ...gitiles.LogOption) error); ok {
		r0 = rf(ctx, logExpr, fn, opts...)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// LogLinear provides a mock function with given fields: ctx, from, to, opts
func (_m *GitilesRepo) LogLinear(ctx context.Context, from string, to string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, from, to)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	if len(ret) == 0 {
		panic("no return value specified for LogLinear")
	}

	var r0 []*vcsinfo.LongCommit
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error)); ok {
		return rf(ctx, from, to, opts...)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, from, to, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, from, to, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadFile provides a mock function with given fields: ctx, srcPath
func (_m *GitilesRepo) ReadFile(ctx context.Context, srcPath string) ([]byte, error) {
	ret := _m.Called(ctx, srcPath)

	if len(ret) == 0 {
		panic("no return value specified for ReadFile")
	}

	var r0 []byte
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) ([]byte, error)); ok {
		return rf(ctx, srcPath)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) []byte); ok {
		r0 = rf(ctx, srcPath)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]byte)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, srcPath)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadFileAtRef provides a mock function with given fields: ctx, srcPath, ref
func (_m *GitilesRepo) ReadFileAtRef(ctx context.Context, srcPath string, ref string) ([]byte, error) {
	ret := _m.Called(ctx, srcPath, ref)

	if len(ret) == 0 {
		panic("no return value specified for ReadFileAtRef")
	}

	var r0 []byte
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) ([]byte, error)); ok {
		return rf(ctx, srcPath, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []byte); ok {
		r0 = rf(ctx, srcPath, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]byte)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, srcPath, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadObject provides a mock function with given fields: ctx, path, ref
func (_m *GitilesRepo) ReadObject(ctx context.Context, path string, ref string) (fs.FileInfo, []byte, error) {
	ret := _m.Called(ctx, path, ref)

	if len(ret) == 0 {
		panic("no return value specified for ReadObject")
	}

	var r0 fs.FileInfo
	var r1 []byte
	var r2 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) (fs.FileInfo, []byte, error)); ok {
		return rf(ctx, path, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string, string) fs.FileInfo); ok {
		r0 = rf(ctx, path, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(fs.FileInfo)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string, string) []byte); ok {
		r1 = rf(ctx, path, ref)
	} else {
		if ret.Get(1) != nil {
			r1 = ret.Get(1).([]byte)
		}
	}

	if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
		r2 = rf(ctx, path, ref)
	} else {
		r2 = ret.Error(2)
	}

	return r0, r1, r2
}

// ResolveRef provides a mock function with given fields: ctx, ref
func (_m *GitilesRepo) ResolveRef(ctx context.Context, ref string) (string, error) {
	ret := _m.Called(ctx, ref)

	if len(ret) == 0 {
		panic("no return value specified for ResolveRef")
	}

	var r0 string
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok {
		return rf(ctx, ref)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
		r0 = rf(ctx, ref)
	} else {
		r0 = ret.Get(0).(string)
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Tags provides a mock function with given fields: ctx
func (_m *GitilesRepo) Tags(ctx context.Context) (map[string]string, error) {
	ret := _m.Called(ctx)

	if len(ret) == 0 {
		panic("no return value specified for Tags")
	}

	var r0 map[string]string
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context) (map[string]string, error)); ok {
		return rf(ctx)
	}
	if rf, ok := ret.Get(0).(func(context.Context) map[string]string); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[string]string)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// URL provides a mock function with given fields:
func (_m *GitilesRepo) URL() string {
	ret := _m.Called()

	if len(ret) == 0 {
		panic("no return value specified for URL")
	}

	var r0 string
	if rf, ok := ret.Get(0).(func() string); ok {
		r0 = rf()
	} else {
		r0 = ret.Get(0).(string)
	}

	return r0
}

// NewGitilesRepo creates a new instance of GitilesRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewGitilesRepo(t interface {
	mock.TestingT
	Cleanup(func())
}) *GitilesRepo {
	mock := &GitilesRepo{}
	mock.Mock.Test(t)

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
