summaryrefslogtreecommitdiff
path: root/git-log-describe.awk
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-11-22 23:32:42 +0100
committerPeter Wu <lekensteyn@gmail.com>2013-11-22 23:34:26 +0100
commit033551b758ce400a2209ef2e8223abb3cf17ebed (patch)
tree13f1e200fab9c234e22d3855f4a145bb951398ff /git-log-describe.awk
parent8a7fc4cce342c178260869e20913aced8994826a (diff)
downloadscripts-033551b758ce400a2209ef2e8223abb3cf17ebed.tar.gz
git-log-describe: introduce cache to speed up git-describe
git-describe is slow, this change allows the output to be cached in a directory using two levels (first two chars of hash for a directory, the remaining 38 for the file). Set `-vcache=1` to enable the cache or specify a custom cache directory with `-vcache_dir=DIR`. On the Linux tree, this feature decreases the run time from 18 seconds to just one second (with .git in already in disk cache for both trials and 466 commits for a certain path).
Diffstat (limited to 'git-log-describe.awk')
-rwxr-xr-xgit-log-describe.awk92
1 files changed, 83 insertions, 9 deletions
diff --git a/git-log-describe.awk b/git-log-describe.awk
index c4f7fee..27063c4 100755
--- a/git-log-describe.awk
+++ b/git-log-describe.awk
@@ -2,13 +2,30 @@
# Adds a "git describe" (nearest tag) output for `git log` (with support for
# color escapes and --graph markers). --oneline is not supported.
#
+# Optional variables:
+# -vcache={0|1} Enable a cache for git describe outputs. If set to 1,
+# .git/describe-cache.d/ as default cache_dir.
+# -vcache_dir=DIR Use DIR to store cached git-describe results. DIR will
+# be created if non-existent. Implies -vcache=1.
+# -vcache_ro={0|1} Set to 1 to prevent creating new files in cache.
+#
# Copyright (c) 2013 Peter Wu <lekensteyn@gmail.com>
# Licensed under GPLv3 or any latter version
-function has_color(str) {
- if (str ~ /\033/) return 1;
+BEGIN {
+ if (!cache_dir && cache) {
+ # Use directory in .git/ as default.
+ "git rev-parse --show-toplevel" | getline cache_dir;
+ if (cache_dir)
+ cache_dir = cache_dir "/.git/describe-cache.d";
+ }
- return 0;
+ if (cache_dir) {
+ # Skip cache directory if non-existent and read only or if the
+ # directory cannot be created.
+ if (cache_ro && !is_dir(cache_dir) || !mkdir_p(cache_dir))
+ cache_dir = "";
+ }
}
{ print; }
@@ -26,12 +43,69 @@ function has_color(str) {
# match only git's "commit" label, not something from the commit message.
$0 ~ /^commit/ &&
-$1 == "commit" && $2 ~ /^[0-9a-f]{5,40}$/ {
+$1 == "commit" && $2 ~ /^[0-9a-f]{4,40}$/ {
hash = $2;
+ desc = git_describe(hash);
+
+ if (desc) {
+ printf("%" indent_len "sDescribe: ", "");
+
+ if (is_color)
+ print "\033[96m" desc "\033[m"; # light cyan
+ else
+ print desc;
+ }
+}
+
+# Helper functions
+function shellescape(arg) {
+ gsub(/'/, "'\\''", arg);
+ return "'" arg "'";
+}
+
+function is_dir(path) {
+ return system("test -d " shellescape(path)) == 0;
+}
+
+function mkdir_p(dir) {
+ return system("mkdir -p -- " shellescape(dir)) == 0;
+}
+
+function has_color(str) {
+ if (str ~ /\033/) return 1;
+
+ return 0;
+}
+
+# Show the name matching the sha1 hash (consisting of 4-40 hexadecimals).
+function git_describe(hash) {
+ desc = "";
+
+ if (length(hash) != 40) {
+ "git rev-parse --default " hash | getline hash;
+
+ if (length(hash) != 40) return "";
+ }
+
+ # try cached output if enabled/any.
+ if (cache_dir) {
+ cache_subdir = cache_dir "/" substr(hash, 1, 2);
+ cache_file = cache_subdir "/" substr(hash, 3);
+ getline desc < cache_file;
+ close(cache_file);
+ }
+
+ # cache entry was unavailable, get a description now.
+ if (!desc) {
+ "git describe --first-parent " hash | getline desc;
+
+ # write description to cache if allowed.
+ if (cache_dir && desc && !cache_ro) {
+ mkdir_p(cache_subdir);
+ print desc > cache_file;
+ close(cache_file);
+ }
+ }
- printf("%" indent_len "sDescribe: ", "");
- if (is_color) printf("\033[96m"); # light cyan
- system("git describe --first-parent " hash " | tr -d '\n'");
- if (is_color) printf("\033[m");
- printf("\n");
+ return desc;
}