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 The implementation currently uses the builtin checker that exist in git. The
7 intention though is to have a checker that doesn't relay on git, independent.
8 
9 TODO:
10  * whitespace check of specific files.
11  * checker that can work without git.
12 */
13 module autoformat.tool_whitespace_check;
14 
15 import std.algorithm;
16 import std.array;
17 import std.exception;
18 import std.process : execute;
19 
20 import logger = std.experimental.logger;
21 
22 import autoformat.git : isGitRepo, gitHead;
23 import autoformat.types;
24 
25 auto runWhitespaceCheck() nothrow {
26     final switch (isGitDirectory) {
27     case GitDirectory.unknown:
28         isGitDirectory = GitDirectory.other;
29 
30         try {
31             import std.file : getcwd;
32 
33             if (isGitRepo == 0) {
34                 return FormatterResult(FailedWithUserMsg("Trailing whitespace detector only work when ran from inside a git repo. The current directory is NOT a git repo: " ~ getcwd));
35             }
36         } catch (Exception ex) {
37             return FormatterResult(FailedWithUserMsg(
38                     "Aborting trailing whitespace check, unable to determine if the current directory is a git repo"));
39         }
40 
41         isGitDirectory = GitDirectory.git;
42         break;
43     case GitDirectory.git:
44         break;
45     case GitDirectory.other:
46         return FormatterResult(Unchanged.init);
47     }
48 
49     auto rval = FormatterResult(FormatError.init);
50     auto against = gitHead;
51 
52     try {
53         auto arg = ["git", "diff-index", "--check", "--cached", against, "--"];
54         logger.trace(arg.join(" "));
55         auto res = execute(arg);
56         logger.trace(res.output);
57 
58         if (res.status == 0) {
59             rval = Unchanged.init;
60         } else {
61             rval = FailedWithUserMsg(
62                     "Trailing whitespace check failed. Fix these files to pass the check:\n"
63                     ~ res.output);
64         }
65     } catch (Exception ex) {
66         rval = FailedWithUserMsg(ex.msg);
67     }
68 
69     return rval;
70 }
71 
72 private:
73 
74 // Thread local detection if the current directory reside in a git archive.
75 GitDirectory isGitDirectory = GitDirectory.unknown;
76 
77 enum GitDirectory {
78     unknown,
79     git,
80     other
81 }