1 /* 2 * Copyright (C) the libgit2 contributors. All rights reserved. 3 * 4 * This file is part of libgit2, distributed under the GNU GPL v2 with 5 * a Linking Exception. For full terms see the included COPYING file. 6 */ 7 #ifndef INCLUDE_attr_file_h__ 8 #define INCLUDE_attr_file_h__ 9 10 #include "common.h" 11 12 #include "git2/oid.h" 13 #include "git2/attr.h" 14 #include "vector.h" 15 #include "pool.h" 16 #include "buffer.h" 17 #include "futils.h" 18 19 #define GIT_ATTR_FILE ".gitattributes" 20 #define GIT_ATTR_FILE_INREPO "attributes" 21 #define GIT_ATTR_FILE_SYSTEM "gitattributes" 22 #define GIT_ATTR_FILE_XDG "attributes" 23 24 #define GIT_ATTR_FNMATCH_NEGATIVE (1U << 0) 25 #define GIT_ATTR_FNMATCH_DIRECTORY (1U << 1) 26 #define GIT_ATTR_FNMATCH_FULLPATH (1U << 2) 27 #define GIT_ATTR_FNMATCH_MACRO (1U << 3) 28 #define GIT_ATTR_FNMATCH_IGNORE (1U << 4) 29 #define GIT_ATTR_FNMATCH_HASWILD (1U << 5) 30 #define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6) 31 #define GIT_ATTR_FNMATCH_ICASE (1U << 7) 32 #define GIT_ATTR_FNMATCH_MATCH_ALL (1U << 8) 33 #define GIT_ATTR_FNMATCH_ALLOWNEG (1U << 9) 34 #define GIT_ATTR_FNMATCH_ALLOWMACRO (1U << 10) 35 36 #define GIT_ATTR_FNMATCH__INCOMING \ 37 (GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO) 38 39 typedef enum { 40 GIT_ATTR_FILE_SOURCE_MEMORY = 0, 41 GIT_ATTR_FILE_SOURCE_FILE = 1, 42 GIT_ATTR_FILE_SOURCE_INDEX = 2, 43 GIT_ATTR_FILE_SOURCE_HEAD = 3, 44 GIT_ATTR_FILE_SOURCE_COMMIT = 4, 45 46 GIT_ATTR_FILE_NUM_SOURCES = 5 47 } git_attr_file_source_t; 48 49 typedef struct { 50 /* The source location for the attribute file. */ 51 git_attr_file_source_t type; 52 53 /* 54 * The filename of the attribute file to read (relative to the 55 * given base path). 56 */ 57 const char *base; 58 const char *filename; 59 60 /* 61 * The commit ID when the given source type is a commit (or NULL 62 * for the repository's HEAD commit.) 63 */ 64 git_oid *commit_id; 65 } git_attr_file_source; 66 67 extern const char *git_attr__true; 68 extern const char *git_attr__false; 69 extern const char *git_attr__unset; 70 71 typedef struct { 72 char *pattern; 73 size_t length; 74 char *containing_dir; 75 size_t containing_dir_length; 76 unsigned int flags; 77 } git_attr_fnmatch; 78 79 typedef struct { 80 git_attr_fnmatch match; 81 git_vector assigns; /* vector of <git_attr_assignment*> */ 82 } git_attr_rule; 83 84 typedef struct { 85 git_refcount unused; 86 const char *name; 87 uint32_t name_hash; 88 } git_attr_name; 89 90 typedef struct { 91 git_refcount rc; /* for macros */ 92 char *name; 93 uint32_t name_hash; 94 const char *value; 95 } git_attr_assignment; 96 97 typedef struct git_attr_file_entry git_attr_file_entry; 98 99 typedef struct { 100 git_refcount rc; 101 git_mutex lock; 102 git_attr_file_entry *entry; 103 git_attr_file_source source; 104 git_vector rules; /* vector of <rule*> or <fnmatch*> */ 105 git_pool pool; 106 unsigned int nonexistent:1; 107 int session_key; 108 union { 109 git_oid oid; 110 git_futils_filestamp stamp; 111 } cache_data; 112 } git_attr_file; 113 114 struct git_attr_file_entry { 115 git_attr_file *file[GIT_ATTR_FILE_NUM_SOURCES]; 116 const char *path; /* points into fullpath */ 117 char fullpath[GIT_FLEX_ARRAY]; 118 }; 119 120 typedef struct { 121 git_buf full; 122 char *path; 123 char *basename; 124 int is_dir; 125 } git_attr_path; 126 127 /* A git_attr_session can provide an "instance" of reading, to prevent cache 128 * invalidation during a single operation instance (like checkout). 129 */ 130 131 typedef struct { 132 int key; 133 unsigned int init_setup:1, 134 init_sysdir:1; 135 git_buf sysdir; 136 git_buf tmp; 137 } git_attr_session; 138 139 extern int git_attr_session__init(git_attr_session *attr_session, git_repository *repo); 140 extern void git_attr_session__free(git_attr_session *session); 141 142 extern int git_attr_get_many_with_session( 143 const char **values_out, 144 git_repository *repo, 145 git_attr_session *attr_session, 146 git_attr_options *opts, 147 const char *path, 148 size_t num_attr, 149 const char **names); 150 151 typedef int (*git_attr_file_parser)( 152 git_repository *repo, 153 git_attr_file *file, 154 const char *data, 155 bool allow_macros); 156 157 /* 158 * git_attr_file API 159 */ 160 161 int git_attr_file__new( 162 git_attr_file **out, 163 git_attr_file_entry *entry, 164 git_attr_file_source *source); 165 166 void git_attr_file__free(git_attr_file *file); 167 168 int git_attr_file__load( 169 git_attr_file **out, 170 git_repository *repo, 171 git_attr_session *attr_session, 172 git_attr_file_entry *ce, 173 git_attr_file_source *source, 174 git_attr_file_parser parser, 175 bool allow_macros); 176 177 int git_attr_file__load_standalone( 178 git_attr_file **out, const char *path); 179 180 int git_attr_file__out_of_date( 181 git_repository *repo, git_attr_session *session, git_attr_file *file, git_attr_file_source *source); 182 183 int git_attr_file__parse_buffer( 184 git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros); 185 186 int git_attr_file__clear_rules( 187 git_attr_file *file, bool need_lock); 188 189 int git_attr_file__lookup_one( 190 git_attr_file *file, 191 git_attr_path *path, 192 const char *attr, 193 const char **value); 194 195 /* loop over rules in file from bottom to top */ 196 #define git_attr_file__foreach_matching_rule(file, path, iter, rule) \ 197 git_vector_rforeach(&(file)->rules, (iter), (rule)) \ 198 if (git_attr_rule__match((rule), (path))) 199 200 uint32_t git_attr_file__name_hash(const char *name); 201 202 203 /* 204 * other utilities 205 */ 206 207 extern int git_attr_fnmatch__parse( 208 git_attr_fnmatch *spec, 209 git_pool *pool, 210 const char *source, 211 const char **base); 212 213 extern bool git_attr_fnmatch__match( 214 git_attr_fnmatch *rule, 215 git_attr_path *path); 216 217 extern void git_attr_rule__free(git_attr_rule *rule); 218 219 extern bool git_attr_rule__match( 220 git_attr_rule *rule, 221 git_attr_path *path); 222 223 extern git_attr_assignment *git_attr_rule__lookup_assignment( 224 git_attr_rule *rule, const char *name); 225 226 typedef enum { GIT_DIR_FLAG_TRUE = 1, GIT_DIR_FLAG_FALSE = 0, GIT_DIR_FLAG_UNKNOWN = -1 } git_dir_flag; 227 228 extern int git_attr_path__init( 229 git_attr_path *out, 230 const char *path, 231 const char *base, 232 git_dir_flag is_dir); 233 extern void git_attr_path__free(git_attr_path *info); 234 235 extern int git_attr_assignment__parse( 236 git_repository *repo, /* needed to expand macros */ 237 git_pool *pool, 238 git_vector *assigns, 239 const char **scan); 240 241 #endif 242