summaryrefslogtreecommitdiff
path: root/ws.c
diff options
context:
space:
mode:
Diffstat (limited to 'ws.c')
-rw-r--r--ws.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/ws.c b/ws.c
new file mode 100644
index 0000000000..52c10caf35
--- /dev/null
+++ b/ws.c
@@ -0,0 +1,96 @@
+/*
+ * Whitespace rules
+ *
+ * Copyright (c) 2007 Junio C Hamano
+ */
+
+#include "cache.h"
+#include "attr.h"
+
+static struct whitespace_rule {
+ const char *rule_name;
+ unsigned rule_bits;
+} whitespace_rule_names[] = {
+ { "trailing-space", WS_TRAILING_SPACE },
+ { "space-before-tab", WS_SPACE_BEFORE_TAB },
+ { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB },
+};
+
+unsigned parse_whitespace_rule(const char *string)
+{
+ unsigned rule = WS_DEFAULT_RULE;
+
+ while (string) {
+ int i;
+ size_t len;
+ const char *ep;
+ int negated = 0;
+
+ string = string + strspn(string, ", \t\n\r");
+ ep = strchr(string, ',');
+ if (!ep)
+ len = strlen(string);
+ else
+ len = ep - string;
+
+ if (*string == '-') {
+ negated = 1;
+ string++;
+ len--;
+ }
+ if (!len)
+ break;
+ for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) {
+ if (strncmp(whitespace_rule_names[i].rule_name,
+ string, len))
+ continue;
+ if (negated)
+ rule &= ~whitespace_rule_names[i].rule_bits;
+ else
+ rule |= whitespace_rule_names[i].rule_bits;
+ break;
+ }
+ string = ep;
+ }
+ return rule;
+}
+
+static void setup_whitespace_attr_check(struct git_attr_check *check)
+{
+ static struct git_attr *attr_whitespace;
+
+ if (!attr_whitespace)
+ attr_whitespace = git_attr("whitespace", 10);
+ check[0].attr = attr_whitespace;
+}
+
+unsigned whitespace_rule(const char *pathname)
+{
+ struct git_attr_check attr_whitespace_rule;
+
+ setup_whitespace_attr_check(&attr_whitespace_rule);
+ if (!git_checkattr(pathname, 1, &attr_whitespace_rule)) {
+ const char *value;
+
+ value = attr_whitespace_rule.value;
+ if (ATTR_TRUE(value)) {
+ /* true (whitespace) */
+ unsigned all_rule = 0;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++)
+ all_rule |= whitespace_rule_names[i].rule_bits;
+ return all_rule;
+ } else if (ATTR_FALSE(value)) {
+ /* false (-whitespace) */
+ return 0;
+ } else if (ATTR_UNSET(value)) {
+ /* reset to default (!whitespace) */
+ return whitespace_rule_cfg;
+ } else {
+ /* string */
+ return parse_whitespace_rule(value);
+ }
+ } else {
+ return whitespace_rule_cfg;
+ }
+}