1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This file contains functions for git repos. 7 */ 8 module autoformat.git; 9 10 import std.exception; 11 import std.file; 12 import std.path; 13 import std.process; 14 15 import my.optional; 16 17 import autoformat.types; 18 19 bool isGitRoot(AbsolutePath arg_p) nothrow { 20 if (!exists(arg_p)) { 21 return false; 22 } else if (exists(buildPath(arg_p, ".git", "refs"))) { 23 // all is well! a real git repo found 24 return true; 25 } else if (exists(buildPath(arg_p, "refs"))) { 26 // humpf, submodule 27 return true; 28 } 29 30 return false; 31 } 32 33 /// If the current working directory is a git repo 34 bool isGitRepo() nothrow { 35 try { 36 auto r = execute(["git", "rev-parse", "--show-toplevel"]); 37 return r.status == 0; 38 } catch (Exception ex) { 39 } 40 41 return false; 42 } 43 44 Optional!AbsolutePath gitHookPath(AbsolutePath repo) { 45 immutable regular = buildPath(repo, ".git", "hooks"); 46 immutable submodule = buildPath(repo, "hooks"); 47 48 if (exists(regular)) { 49 return some(AbsolutePath(regular)); 50 } else if (exists(buildPath(repo, "refs"))) { 51 return some(AbsolutePath(submodule)); 52 } 53 54 return none!AbsolutePath; 55 } 56 57 /// Path to the root of the git archive from current. 58 Optional!AbsolutePath gitPathToRoot() @safe { 59 import std.string : strip; 60 61 try { 62 auto r = execute(["git", "rev-parse", "--show-toplevel"]); 63 return some(AbsolutePath(r.output.strip)); 64 } catch (Exception ex) { 65 } 66 67 return none!AbsolutePath; 68 } 69 70 /** Resolves the path to the git directory. 71 * Not necessarily the same as the root. 72 * Useful for finding the root of a hierarchy of submodules. 73 */ 74 Optional!AbsolutePath gitPathToTrueRoot() nothrow { 75 import std.string : strip; 76 77 try { 78 auto p = buildPath(gitPathToRoot.toString, ".git"); 79 auto r = execute(["git", "rev-parse", "--resolve-git-dir", p]); 80 return some(AbsolutePath(r.output.strip)); 81 } catch (Exception ex) { 82 } 83 84 return none!AbsolutePath; 85 } 86 87 Optional!string gitConfigValue(string c) { 88 import std.string : strip; 89 90 try { 91 auto a = execute(["git", "config", c]); 92 if (a.status != 0) { 93 return none!string; 94 } 95 96 return some(a.output.strip); 97 } catch (ErrnoException ex) { 98 } 99 100 return none!string; 101 } 102 103 struct GitHash { 104 string value; 105 alias value this; 106 } 107 108 GitHash gitHead() nothrow { 109 import std.string : strip; 110 111 // Initial commit: diff against an empty tree object 112 auto h = GitHash("4b825dc642cb6eb9a060e54bf8d69288fbee4904"); 113 114 try { 115 auto res = execute(["git", "rev-parse", "--verify", "HEAD"]); 116 if (res.status == 0) { 117 h = GitHash(res.output.strip); 118 } 119 } catch (Exception ex) { 120 } 121 122 return h; 123 }