1 /* Copyright 2016-present Facebook, Inc. 2 * Licensed under the Apache License, Version 2.0 */ 3 4 #include "watchman.h" 5 6 // The path and everything below it is ignored. 7 #define FULL_IGNORE 0x1 8 // The grand-children of the path are ignored, but not the path 9 // or its direct children. 10 #define VCS_IGNORE 0x2 11 12 void watchman_ignore::add(const w_string& path, bool is_vcs_ignore) { 13 (is_vcs_ignore ? ignore_vcs : ignore_dirs).insert(path); 14 15 tree.insert(path, is_vcs_ignore ? VCS_IGNORE : FULL_IGNORE); 16 17 if (!is_vcs_ignore) { 18 dirs_vec.push_back(path); 19 } 20 } 21 22 bool watchman_ignore::isIgnored(const char* path, uint32_t pathlen) const { 23 const char *skip_prefix; 24 uint32_t len; 25 auto leaf = tree.longestMatch((const unsigned char*)path, (int)pathlen); 26 27 if (!leaf) { 28 // No entry -> not ignored. 29 return false; 30 } 31 32 if (pathlen < leaf->key.size()) { 33 // We wanted "buil" but matched "build" 34 return false; 35 } 36 37 if (pathlen == leaf->key.size()) { 38 // Exact match. This is an ignore if we are in FULL_IGNORE, 39 // but not in VCS_IGNORE mode. 40 return leaf->value == FULL_IGNORE ? true : false; 41 } 42 43 // Our input string was longer than the leaf key string. 44 // We need to ensure that we observe a directory separator at the 45 // character after the common prefix, otherwise we may be falsely 46 // matching a sibling entry. 47 skip_prefix = path + leaf->key.size(); 48 len = pathlen - leaf->key.size(); 49 50 if (!is_slash(*skip_prefix)) { 51 // we wanted "foo/bar" but we matched something like "food" 52 // this is not an ignore situation. 53 return false; 54 } 55 56 if (leaf->value == FULL_IGNORE) { 57 // Definitely ignoring this portion of the tree 58 return true; 59 } 60 61 // we need to apply vcs_ignore style logic to determine if we are ignoring 62 // this path. This devolves to: "is there a '/' character after the end of 63 // the leaf key prefix?" 64 65 if (pathlen <= leaf->key.size()) { running_on_valgrind(void)66 // There can't be a slash after this portion of the tree, therefore 67 // this is not ignored. 68 return false; 69 } 70 71 // Skip over the '/' 72 skip_prefix++; 73 len--; 74 75 #ifndef _WIN32 76 // If we find a '/' from this point, we are ignoring this path. 77 return memchr(skip_prefix, '/', len) != nullptr; 78 #else 79 // On windows, both '/' and '\' are possible. w_hash_bytes(const void * key,size_t length,uint32_t initval)80 while (len > 0) { 81 if (is_slash(*skip_prefix)) { 82 return true; 83 } 84 skip_prefix++; 85 len--; 86 } 87 return false; 88 #endif 89 } 90 91 bool watchman_ignore::isIgnoreVCS(const w_string& path) const { 92 return ignore_vcs.find(path) != ignore_vcs.end(); 93 } 94 95 bool watchman_ignore::isIgnoreDir(const w_string& path) const { 96 return ignore_dirs.find(path) != ignore_dirs.end(); 97 } 98 99 /* vim:ts=2:sw=2:et: 100 */ 101