// Code generated by mockery v1.0.0. DO NOT EDIT.

package mocks

import context "context"
import mock "github.com/stretchr/testify/mock"
import time "time"
import vcsinfo "go.skia.org/infra/go/vcsinfo"

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

// ByIndex provides a mock function with given fields: ctx, N
func (_m *VCS) ByIndex(ctx context.Context, N int) (*vcsinfo.LongCommit, error) {
	ret := _m.Called(ctx, N)

	var r0 *vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, int) *vcsinfo.LongCommit); ok {
		r0 = rf(ctx, N)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*vcsinfo.LongCommit)
		}
	}

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

	return r0, r1
}

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

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

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

	return r0, r1
}

// DetailsMulti provides a mock function with given fields: ctx, hashes, includeBranchInfo
func (_m *VCS) DetailsMulti(ctx context.Context, hashes []string, includeBranchInfo bool) ([]*vcsinfo.LongCommit, error) {
	ret := _m.Called(ctx, hashes, includeBranchInfo)

	var r0 []*vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, []string, bool) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, hashes, includeBranchInfo)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, []string, bool) error); ok {
		r1 = rf(ctx, hashes, includeBranchInfo)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// From provides a mock function with given fields: start
func (_m *VCS) From(start time.Time) []string {
	ret := _m.Called(start)

	var r0 []string
	if rf, ok := ret.Get(0).(func(time.Time) []string); ok {
		r0 = rf(start)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]string)
		}
	}

	return r0
}

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

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

	return r0
}

// GetFile provides a mock function with given fields: ctx, fileName, commitHash
func (_m *VCS) GetFile(ctx context.Context, fileName string, commitHash string) (string, error) {
	ret := _m.Called(ctx, fileName, commitHash)

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

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

	return r0, r1
}

// IndexOf provides a mock function with given fields: ctx, hash
func (_m *VCS) IndexOf(ctx context.Context, hash string) (int, error) {
	ret := _m.Called(ctx, hash)

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

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

	return r0, r1
}

// LastNIndex provides a mock function with given fields: N
func (_m *VCS) LastNIndex(N int) []*vcsinfo.IndexCommit {
	ret := _m.Called(N)

	var r0 []*vcsinfo.IndexCommit
	if rf, ok := ret.Get(0).(func(int) []*vcsinfo.IndexCommit); ok {
		r0 = rf(N)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.IndexCommit)
		}
	}

	return r0
}

// Range provides a mock function with given fields: begin, end
func (_m *VCS) Range(begin time.Time, end time.Time) []*vcsinfo.IndexCommit {
	ret := _m.Called(begin, end)

	var r0 []*vcsinfo.IndexCommit
	if rf, ok := ret.Get(0).(func(time.Time, time.Time) []*vcsinfo.IndexCommit); ok {
		r0 = rf(begin, end)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.IndexCommit)
		}
	}

	return r0
}

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

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

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

	return r0, r1
}

// Update provides a mock function with given fields: ctx, pull, allBranches
func (_m *VCS) Update(ctx context.Context, pull bool, allBranches bool) error {
	ret := _m.Called(ctx, pull, allBranches)

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

	return r0
}
