Skip to content

Commit

Permalink
Add git config cache for performance (#77)
Browse files Browse the repository at this point in the history
- Improve runner execution time (no-load) by loading the Git config into a cache.
  This improves runtime 2-3x on Linux/Windows. 
  Loading the whole config is faster than several times accessing different values.
  • Loading branch information
gabyx authored Dec 27, 2021
1 parent 1e86fdb commit ac2770b
Show file tree
Hide file tree
Showing 31 changed files with 536 additions and 137 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ not globally be defined.
| `GITHOOKS_OS` (defined) | The operating system. <br>See [Exported Environment Variables](#exported-environment-variables). |
| `GITHOOKS_ARCH` (defined) | The system architecture. <br>See [Exported Environment Variables](#exported-environment-variables). |
| `GITHOOKS_DISABLE` | If defined, disables running hooks run by Githooks,<br>except `git lfs` and the replaced old hooks. |
| `GITHOOKS_RUNNER_TRACE` | If defined, enables tracing during <br>Githooks runner execution. |
| `GITHOOKS_RUNNER_TRACE` | If defined, enables tracing during <br>Githooks runner execution. A value of `1` enables more output. |
| `GITHOOKS_SKIP_NON_EXISTING_SHARED_HOOKS=true` | Skips on `true` and fails on `false` (or empty) for non-existing shared hooks. <br>See [Trusting Hooks](#trusting-hooks). |
| `GITHOOKS_SKIP_UNTRUSTED_HOOKS=true` | Skips on `true` and fails on `false` (or empty) for untrusted hooks. <br>See [Trusting Hooks](#trusting-hooks). |

Expand Down Expand Up @@ -728,8 +728,8 @@ cli installer \

This will only support the mentioned hooks in the template directory (e.g. for
new clones). You can still overwrite selectively for a repository by
[installing another set of hooks](#installing-or-removing-run-wrappers).
Missing Git LFS hooks will always be placed if necessary.
[installing another set of hooks](#installing-or-removing-run-wrappers). Missing
Git LFS hooks will always be placed if necessary.

If you want, you can try out what the script would do first, without changing
anything by using:
Expand Down
2 changes: 1 addition & 1 deletion githooks/apps/dialog/tools/generate-doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func fixFiles(files []string) {

func main() {

root, err := git.Ctx().Get("rev-parse", "--show-toplevel")
root, err := git.NewCtx().Get("rev-parse", "--show-toplevel")
cm.AssertNoErrorPanic(err, "Could not root dir.")

docRoot := path.Join(root, "docs", "dialog")
Expand Down
22 changes: 14 additions & 8 deletions githooks/apps/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func mainRun() (exitCode int) {
if cm.IsBenchmark {
startTime := cm.GetStartTime()
defer func() {
log.InfoF("Runner execution time: '%v'.",
cm.GetDuration(startTime))
log.InfoF("Runner execution time: '%v' ms.",
float64(cm.GetDuration(startTime))/float64(time.Millisecond))
}()
}

Expand Down Expand Up @@ -122,8 +122,11 @@ func createLog() {
}

func logInvocation(s *HookSettings) {
if strs.IsNotEmpty(os.Getenv("GITHOOKS_RUNNER_TRACE")) {
log.InfoF("Running hooks for: '%s' %q", s.HookName, s.Args)
t := os.Getenv("GITHOOKS_RUNNER_TRACE")
if strs.IsNotEmpty(t) {
log.DebugF("Running hooks for: '%s' %q", s.HookName, s.Args)
} else if t == "1" || cm.IsDebug {
log.DebugF("Settings:\n%s", s.toString())
}
}

Expand All @@ -137,10 +140,12 @@ func setupSettings(repoPath string) (HookSettings, UISettings) {
execx := cm.ExecContext{}

// Current git context, in current working dir.
gitx := git.Ctx()
gitx := git.NewCtx()
log.AssertNoErrorF(gitx.InitConfigCache(nil),
"Could not init git config cache.")

gitDir, err := gitx.GetGitDirWorktree()
cm.AssertNoErrorPanic(err, "Could not get git directory.")
log.AssertNoErrorPanic(err, "Could not get git directory.")

err = hooks.DeleteHookDirTemp(path.Join(gitDir, "hooks"))
log.AssertNoErrorF(err, "Could not clean temporary directory in '%s/hooks'.", gitDir)
Expand Down Expand Up @@ -183,7 +188,6 @@ func setupSettings(repoPath string) (HookSettings, UISettings) {
SkipUntrustedHooks: skipUntrustedHooks,
NonInteractive: nonInteractive}

log.DebugF(s.toString())
logInvocation(&s)

return s, UISettings{AcceptAllChanges: false, PromptCtx: promptx}
Expand Down Expand Up @@ -445,6 +449,7 @@ func executeOldHook(
}

hooks, _, err := hooks.GetAllHooksIn(
settings.GitX,
settings.RepositoryDir,
settings.HookDir, hookName, hookNamespace,
isIgnored, isTrusted, true, false)
Expand Down Expand Up @@ -675,7 +680,7 @@ func checkSharedHook(
// is the same as the specified
// Note: GIT_DIR might be set (?bug?) (actually the case for post-checkout hook)
if hook.IsCloned {
url := git.CtxCSanitized(hook.RepositoryDir).GetConfig(
url := git.NewCtxSanitizedAt(hook.RepositoryDir).GetConfig(
"remote.origin.url", git.LocalScope)

if url != hook.URL {
Expand Down Expand Up @@ -746,6 +751,7 @@ func getHooksIn(
}

allHooks, maxBatches, err := hooks.GetAllHooksIn(
settings.GitX,
rootDir,
hooksDir, settings.HookName, hookNamespace,
isIgnored, isTrusted, true, true)
Expand Down
2 changes: 1 addition & 1 deletion githooks/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func findGoExec(cwd string) (cm.CmdContext, error) {
var err error

// Check from config.
goExec := git.Ctx().GetConfig(hooks.GitCKGoExecutable, git.GlobalScope)
goExec := git.NewCtx().GetConfig(hooks.GitCKGoExecutable, git.GlobalScope)
if strs.IsNotEmpty(goExec) && cm.IsFile(goExec) {
gox = cm.NewCommandCtx(goExec, cwd, nil)

Expand Down
4 changes: 2 additions & 2 deletions githooks/cmd/common/install/readme.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ func setupReadme(
dryRun bool,
uiSettings *UISettings) {

mainWorktree, err := git.CtxC(repoGitDir).GetMainWorktree()
if err != nil || !git.CtxC(mainWorktree).IsGitRepo() {
mainWorktree, err := git.NewCtxAt(repoGitDir).GetMainWorktree()
if err != nil || !git.NewCtxAt(mainWorktree).IsGitRepo() {
log.WarnF("Main worktree could not be determined in:\n'%s'\n"+
"-> Skipping Readme setup.",
repoGitDir)
Expand Down
6 changes: 3 additions & 3 deletions githooks/cmd/common/install/wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func InstallIntoRepo(
log.AssertNoErrorPanic(err,
"Could not create hook directory in '%s'.", repoGitDir)
}
gitxR := git.CtxC(repoGitDir)
gitxR := git.NewCtxAt(repoGitDir)
isBare := gitxR.IsBareRepo()

var err error
Expand Down Expand Up @@ -97,7 +97,7 @@ func cleanArtefactsInRepo(log cm.ILogContext, gitDir string) {
}

func cleanGitConfigInRepo(log cm.ILogContext, gitDir string) {
gitx := git.CtxC(gitDir)
gitx := git.NewCtxAt(gitDir)

for _, k := range hooks.GetLocalGitConfigKeys() {

Expand All @@ -108,7 +108,7 @@ func cleanGitConfigInRepo(log cm.ILogContext, gitDir string) {
}

func unregisterRepo(log cm.ILogContext, gitDir string) {
gitx := git.CtxC(gitDir)
gitx := git.NewCtxAt(gitDir)

log.AssertNoErrorF(hooks.UnmarkRepoRegistered(gitx),
"Could not unregister Git repo '%s'.", gitDir)
Expand Down
6 changes: 3 additions & 3 deletions githooks/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func runList(ctx *ccm.CmdContext, gitOpts *GitOptions) {

maxLength := 0
for i := range pairs {
maxLength = math.MaxInt(maxLength, len(pairs[i][0])+2) // nolint: gomnd
maxLength = math.MaxInt(maxLength, len(pairs[i].Key)+2) // nolint: gomnd
}
keyFmt := strs.Fmt("%%-%vs", maxLength)

Expand All @@ -169,8 +169,8 @@ func runList(ctx *ccm.CmdContext, gitOpts *GitOptions) {
cm.AssertNoErrorPanic(err, "Could not write message.")

for i := range pairs {
key := strs.Fmt("'%s'", pairs[i][0])
_, err = strs.FmtW(&sb, "\n%s "+keyFmt+" : '%s'", cm.ListItemLiteral, key, pairs[i][1])
key := strs.Fmt("'%s'", pairs[i].Key)
_, err = strs.FmtW(&sb, "\n%s "+keyFmt+" : '%s'", cm.ListItemLiteral, key, pairs[i].Value)
cm.AssertNoErrorPanic(err, "Could not write message.")
}

Expand Down
10 changes: 5 additions & 5 deletions githooks/cmd/installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func buildFromSource(

// Checkout the remote commit sha
log.InfoF("Checkout out commit '%s'", commitSHA[0:6])
gitx := git.CtxC(tempDir)
gitx := git.NewCtxAt(tempDir)
err = gitx.Check("checkout",
"-b", "update-to-"+commitSHA[0:6],
commitSHA)
Expand Down Expand Up @@ -1059,7 +1059,7 @@ func setupSharedRepositories(
dryRun bool,
uiSettings *install.UISettings) {

gitx := git.Ctx()
gitx := git.NewCtx()
sharedRepos := gitx.GetConfigAll(hooks.GitCKShared, git.GlobalScope)

var question string
Expand Down Expand Up @@ -1146,7 +1146,7 @@ func storeSettings(log cm.ILogContext, settings *Settings, uiSettings *install.U
// Store cached UI values back.

if strs.IsNotEmpty(uiSettings.DeleteDetectedLFSHooks) {
err := git.Ctx().SetConfig(
err := git.NewCtx().SetConfig(
hooks.GitCKDeleteDetectedLFSHooksAnswer, uiSettings.DeleteDetectedLFSHooks, git.GlobalScope)
log.AssertNoError(err, "Could not store config '%v'.", uiSettings.DeleteDetectedLFSHooks)
}
Expand All @@ -1159,7 +1159,7 @@ func storeSettings(log cm.ILogContext, settings *Settings, uiSettings *install.U
if err != nil {
for _, gitDir := range settings.InstalledGitDirs.ToList() {
// For each installedGitDir entry, mark the repository as registered.
err := hooks.MarkRepoRegistered(git.CtxC(gitDir))
err := hooks.MarkRepoRegistered(git.NewCtxAt(gitDir))
log.AssertNoErrorF(err, "Could not mark Git directory '%s' as registered.", gitDir)
}
}
Expand Down Expand Up @@ -1379,5 +1379,5 @@ func transformLegacyGitConfigSettings(log cm.ILogContext, gitx *git.Context) {
log.AssertNoError(err, "Could not set maintained hooks to 'server'.")
}

_ = git.Ctx().UnsetConfig("githooks.maintainOnlyServerHooks", git.GlobalScope)
_ = git.NewCtx().UnsetConfig("githooks.maintainOnlyServerHooks", git.GlobalScope)
}
20 changes: 14 additions & 6 deletions githooks/cmd/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,25 @@ func listHooksForName(
withBatchName bool) (string, int) {

// List replaced hooks (normally only one)
gitx := git.NewCtxAt(repoDir)
replacedHooks := GetAllHooksIn(
log, repoDir, path.Join(gitDir, "hooks"), hookName,
log, gitx,
repoDir, path.Join(gitDir, "hooks"), hookName,
hooks.NamespaceReplacedHook, state, false, true)

// List repository hooks
repoHooks := GetAllHooksIn(
log, repoDir, repoHooksDir, hookName,
log, gitx,
repoDir, repoHooksDir, hookName,
hooks.NamespaceRepositoryHook, state, false, false)

// List all shared hooks
sharedCount := 0
all := make([]SharedHooks, 0, shared.GetCount())
for idx, sharedRepos := range shared {
coll, count := GetAllHooksInShared(log, hookName, state, sharedRepos, hooks.SharedHookType(idx))
coll, count := GetAllHooksInShared(
log, gitx,
hookName, state, sharedRepos, hooks.SharedHookType(idx))
sharedCount += count
all = append(all, coll...)
}
Expand Down Expand Up @@ -260,6 +265,7 @@ type SharedHooks struct {
// GetAllHooksInShared gets all hooks in shared repositories.
func GetAllHooksInShared(
log cm.ILogContext,
gitx *git.Context,
hookName string,
state *ListingState,
sharedRepos []hooks.SharedRepo,
Expand All @@ -275,15 +281,15 @@ func GetAllHooksInShared(
var allHooks []hooks.Hook

if dir := hooks.GetSharedGithooksDir(shRepo.RepositoryDir); cm.IsDirectory(dir) {
allHooks = GetAllHooksIn(log, shRepo.RepositoryDir,
allHooks = GetAllHooksIn(log, gitx, shRepo.RepositoryDir,
dir, hookName, hookNamespace, state, true, false)

} else if dir := hooks.GetGithooksDir(shRepo.RepositoryDir); cm.IsDirectory(dir) {
allHooks = GetAllHooksIn(log, shRepo.RepositoryDir,
allHooks = GetAllHooksIn(log, gitx, shRepo.RepositoryDir,
dir, hookName, hookNamespace, state, true, false)

} else {
allHooks = GetAllHooksIn(log, shRepo.RepositoryDir,
allHooks = GetAllHooksIn(log, gitx, shRepo.RepositoryDir,
shRepo.RepositoryDir, hookName, hookNamespace, state, true, false)
}

Expand All @@ -303,6 +309,7 @@ func GetAllHooksInShared(
// GetAllHooksIn gets all hooks in a hooks directory.
func GetAllHooksIn(
log cm.ILogContext,
gitx *git.Context,
rootDir string,
hooksDir string,
hookName string,
Expand Down Expand Up @@ -360,6 +367,7 @@ func GetAllHooksIn(
}

allHooks, _, err := hooks.GetAllHooksIn(
gitx,
rootDir, hooksDir,
hookName, hookNamespace,
isIgnored, isTrusted, false,
Expand Down
2 changes: 1 addition & 1 deletion githooks/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NewSettings(
var err error

cwd, err := os.Getwd()
gitx := git.CtxC(cwd)
gitx := git.NewCtxAt(cwd)
log.AssertNoErrorPanic(err, "Could not get current working directory.")

installDir := inst.LoadInstallDir(log, gitx)
Expand Down
10 changes: 7 additions & 3 deletions githooks/cmd/trust/trustHooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/gabyx/githooks/githooks/cmd/ignore"
"github.com/gabyx/githooks/githooks/cmd/list"
cm "github.com/gabyx/githooks/githooks/common"
"github.com/gabyx/githooks/githooks/git"
"github.com/gabyx/githooks/githooks/hooks"

"github.com/spf13/cobra"
Expand All @@ -23,23 +24,26 @@ func getAllHooks(

allHooks = make([]hooks.Hook, 0, 10+2*shared.GetCount()) // nolint: gomnd

gitx := git.NewCtxAt(repoDir)

for _, hookName := range hookNames {

// List replaced hooks (normally only one)
replacedHooks := list.GetAllHooksIn(
log, repoDir, path.Join(gitDir, "hooks"), hookName,
log, gitx, repoDir, path.Join(gitDir, "hooks"), hookName,
hooks.NamespaceReplacedHook, state, false, true)
allHooks = append(allHooks, replacedHooks...)

// List repository hooks
repoHooks := list.GetAllHooksIn(log, repoDir, repoHooksDir, hookName,
repoHooks := list.GetAllHooksIn(log, gitx, repoDir, repoHooksDir, hookName,
hooks.NamespaceRepositoryHook, state, false, false)
allHooks = append(allHooks, repoHooks...)

// List all shared hooks
sharedCount := 0
for idx, sharedRepos := range shared {
coll, count := list.GetAllHooksInShared(log, hookName, state, sharedRepos, hooks.SharedHookType(idx))
coll, count := list.GetAllHooksInShared(log, gitx,
hookName, state, sharedRepos, hooks.SharedHookType(idx))
sharedCount += count

for i := range coll {
Expand Down
Loading

0 comments on commit ac2770b

Please sign in to comment.