From: Junio C Hamano Date: Sun, 17 Feb 2008 01:57:06 +0000 (-0800) Subject: Merge branch 'jc/gitignore-ends-with-slash' X-Git-Tag: v1.5.5-rc0~208 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/987e315a6b5a5dd224602f09b9dc7c0fe9c7d024?hp=-c Merge branch 'jc/gitignore-ends-with-slash' * jc/gitignore-ends-with-slash: gitignore: lazily find dtype gitignore(5): Allow "foo/" in ignore list to match directory "foo" --- 987e315a6b5a5dd224602f09b9dc7c0fe9c7d024 diff --combined builtin-ls-files.c index d56e33e251,54cb2518db..dc7eab89b3 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@@ -189,7 -189,7 +189,7 @@@ static void show_ce_entry(const char *t return; if (tag && *tag && show_valid_bit && - (ce->ce_flags & htons(CE_VALID))) { + (ce->ce_flags & CE_VALID)) { static char alttag[4]; memcpy(alttag, tag, 3); if (isalpha(tag[0])) @@@ -210,7 -210,7 +210,7 @@@ } else { printf("%s%06o %s %d\t", tag, - ntohl(ce->ce_mode), + ce->ce_mode, abbrev ? find_unique_abbrev(ce->sha1,abbrev) : sha1_to_hex(ce->sha1), ce_stage(ce)); @@@ -238,11 -238,12 +238,12 @@@ static void show_files(struct dir_struc if (show_cached | show_stage) { for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; - if (excluded(dir, ce->name) != dir->show_ignored) + int dtype = ce_to_dtype(ce); + if (excluded(dir, ce->name, &dtype) != dir->show_ignored) continue; if (show_unmerged && !ce_stage(ce)) continue; - if (ce->ce_flags & htons(CE_UPDATE)) + if (ce->ce_flags & CE_UPDATE) continue; show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce); } @@@ -252,7 -253,8 +253,8 @@@ struct cache_entry *ce = active_cache[i]; struct stat st; int err; - if (excluded(dir, ce->name) != dir->show_ignored) + int dtype = ce_to_dtype(ce); + if (excluded(dir, ce->name, &dtype) != dir->show_ignored) continue; err = lstat(ce->name, &st); if (show_deleted && err) @@@ -350,7 -352,7 +352,7 @@@ void overlay_tree_on_cache(const char * struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; - ce->ce_flags |= htons(CE_STAGEMASK); + ce->ce_flags |= CE_STAGEMASK; } if (prefix) { @@@ -379,7 -381,7 +381,7 @@@ */ if (last_stage0 && !strcmp(last_stage0->name, ce->name)) - ce->ce_flags |= htons(CE_UPDATE); + ce->ce_flags |= CE_UPDATE; } } } diff --combined cache.h index efd31d8569,5529830110..18fe8447f3 --- a/cache.h +++ b/cache.h @@@ -3,7 -3,6 +3,7 @@@ #include "git-compat-util.h" #include "strbuf.h" +#include "hash.h" #include SHA1_HEADER #include @@@ -95,104 -94,78 +95,116 @@@ struct cache_time * We save the fields in big-endian order to allow using the * index file over NFS transparently. */ +struct ondisk_cache_entry { + struct cache_time ctime; + struct cache_time mtime; + unsigned int dev; + unsigned int ino; + unsigned int mode; + unsigned int uid; + unsigned int gid; + unsigned int size; + unsigned char sha1[20]; + unsigned short flags; + char name[FLEX_ARRAY]; /* more */ +}; + struct cache_entry { - struct cache_time ce_ctime; - struct cache_time ce_mtime; + struct cache_entry *next; + unsigned int ce_ctime; + unsigned int ce_mtime; unsigned int ce_dev; unsigned int ce_ino; unsigned int ce_mode; unsigned int ce_uid; unsigned int ce_gid; unsigned int ce_size; + unsigned int ce_flags; unsigned char sha1[20]; - unsigned short ce_flags; char name[FLEX_ARRAY]; /* more */ }; #define CE_NAMEMASK (0x0fff) #define CE_STAGEMASK (0x3000) -#define CE_UPDATE (0x4000) #define CE_VALID (0x8000) #define CE_STAGESHIFT 12 -#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT)) -#define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags)) +/* In-memory only */ +#define CE_UPDATE (0x10000) +#define CE_REMOVE (0x20000) +#define CE_UPTODATE (0x40000) +#define CE_UNHASHED (0x80000) + +static inline unsigned create_ce_flags(size_t len, unsigned stage) +{ + if (len >= CE_NAMEMASK) + len = CE_NAMEMASK; + return (len | (stage << CE_STAGESHIFT)); +} + +static inline size_t ce_namelen(const struct cache_entry *ce) +{ + size_t len = ce->ce_flags & CE_NAMEMASK; + if (len < CE_NAMEMASK) + return len; + return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK; +} + #define ce_size(ce) cache_entry_size(ce_namelen(ce)) -#define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT) +#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce)) +#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT) +#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) +#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) static inline unsigned int create_ce_mode(unsigned int mode) { if (S_ISLNK(mode)) - return htonl(S_IFLNK); + return S_IFLNK; if (S_ISDIR(mode) || S_ISGITLINK(mode)) - return htonl(S_IFGITLINK); - return htonl(S_IFREG | ce_permissions(mode)); + return S_IFGITLINK; + return S_IFREG | ce_permissions(mode); } static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode) { extern int trust_executable_bit, has_symlinks; if (!has_symlinks && S_ISREG(mode) && - ce && S_ISLNK(ntohl(ce->ce_mode))) + ce && S_ISLNK(ce->ce_mode)) return ce->ce_mode; if (!trust_executable_bit && S_ISREG(mode)) { - if (ce && S_ISREG(ntohl(ce->ce_mode))) + if (ce && S_ISREG(ce->ce_mode)) return ce->ce_mode; return create_ce_mode(0666); } return create_ce_mode(mode); } + static inline int ce_to_dtype(const struct cache_entry *ce) + { + unsigned ce_mode = ntohl(ce->ce_mode); + if (S_ISREG(ce_mode)) + return DT_REG; + else if (S_ISDIR(ce_mode) || S_ISGITLINK(ce_mode)) + return DT_DIR; + else if (S_ISLNK(ce_mode)) + return DT_LNK; + else + return DT_UNKNOWN; + } #define canon_mode(mode) \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK) #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7) +#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7) struct index_state { struct cache_entry **cache; unsigned int cache_nr, cache_alloc, cache_changed; struct cache_tree *cache_tree; time_t timestamp; - void *mmap; - size_t mmap_size; + void *alloc; + unsigned name_hash_initialized : 1; + struct hash_table name_hash; }; extern struct index_state the_index; @@@ -216,7 -189,6 +228,7 @@@ #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL) #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options)) #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options)) +#define cache_name_exists(name, namelen) index_name_exists(&the_index, (name), (namelen)) #endif enum object_type { @@@ -303,7 -275,6 +315,7 @@@ extern int read_index_from(struct index extern int write_index(struct index_state *, int newfd); extern int discard_index(struct index_state *); extern int verify_path(const char *path); +extern int index_name_exists(struct index_state *istate, const char *name, int namelen); extern int index_name_pos(struct index_state *, const char *name, int namelen); #define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */ #define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ @@@ -625,16 -596,11 +637,16 @@@ extern int git_parse_ulong(const char * extern int git_config_int(const char *, const char *); extern unsigned long git_config_ulong(const char *, const char *); extern int git_config_bool(const char *, const char *); +extern int git_config_string(const char **, const char *, const char *); extern int git_config_set(const char *, const char *); extern int git_config_set_multivar(const char *, const char *, const char *, int); extern int git_config_rename_section(const char *, const char *); extern const char *git_etc_gitconfig(void); extern int check_repository_format_version(const char *var, const char *value); +extern int git_env_bool(const char *, int); +extern int git_config_system(void); +extern int git_config_global(void); +extern int config_error_nonbool(const char *); #define MAX_GITNAME (1000) extern char git_default_email[MAX_GITNAME]; @@@ -654,12 -620,12 +666,12 @@@ extern int write_or_whine_pipe(int fd, /* pager.c */ extern void setup_pager(void); -extern char *pager_program; +extern const char *pager_program; extern int pager_in_use(void); extern int pager_use_color; -extern char *editor_program; -extern char *excludes_file; +extern const char *editor_program; +extern const char *excludes_file; /* base85 */ int decode_85(char *dst, const char *line, int linelen); diff --combined dir.c index 6543105b96,292639b156..1f507daff2 --- a/dir.c +++ b/dir.c @@@ -17,6 -17,7 +17,7 @@@ struct path_simplify static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify); + static int get_dtype(struct dirent *de, const char *path); int common_prefix(const char **pathspec) { @@@ -126,18 -127,34 +127,34 @@@ static int no_wildcard(const char *stri void add_exclude(const char *string, const char *base, int baselen, struct exclude_list *which) { - struct exclude *x = xmalloc(sizeof (*x)); + struct exclude *x; + size_t len; + int to_exclude = 1; + int flags = 0; - x->to_exclude = 1; if (*string == '!') { - x->to_exclude = 0; + to_exclude = 0; string++; } - x->pattern = string; + len = strlen(string); + if (len && string[len - 1] == '/') { + char *s; + x = xmalloc(sizeof(*x) + len); + s = (char*)(x+1); + memcpy(s, string, len - 1); + s[len - 1] = '\0'; + string = s; + x->pattern = s; + flags = EXC_FLAG_MUSTBEDIR; + } else { + x = xmalloc(sizeof(*x)); + x->pattern = string; + } + x->to_exclude = to_exclude; x->patternlen = strlen(string); x->base = base; x->baselen = baselen; - x->flags = 0; + x->flags = flags; if (!strchr(string, '/')) x->flags |= EXC_FLAG_NODIR; if (no_wildcard(string)) @@@ -261,7 -278,7 +278,7 @@@ static void prep_exclude(struct dir_str * Return 1 for exclude, 0 for include and -1 for undecided. */ static int excluded_1(const char *pathname, - int pathlen, const char *basename, + int pathlen, const char *basename, int *dtype, struct exclude_list *el) { int i; @@@ -272,6 -289,13 +289,13 @@@ const char *exclude = x->pattern; int to_exclude = x->to_exclude; + if (x->flags & EXC_FLAG_MUSTBEDIR) { + if (*dtype == DT_UNKNOWN) + *dtype = get_dtype(NULL, pathname); + if (*dtype != DT_DIR) + continue; + } + if (x->flags & EXC_FLAG_NODIR) { /* match basename */ if (x->flags & EXC_FLAG_NOWILDCARD) { @@@ -314,7 -338,7 +338,7 @@@ return -1; /* undecided */ } - int excluded(struct dir_struct *dir, const char *pathname) + int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p) { int pathlen = strlen(pathname); int st; @@@ -323,7 -347,8 +347,8 @@@ prep_exclude(dir, pathname, basename-pathname); for (st = EXC_CMDL; st <= EXC_FILE; st++) { - switch (excluded_1(pathname, pathlen, basename, &dir->exclude_list[st])) { + switch (excluded_1(pathname, pathlen, basename, + dtype_p, &dir->exclude_list[st])) { case 0: return 0; case 1: @@@ -346,7 -371,7 +371,7 @@@ static struct dir_entry *dir_entry_new( struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len) { - if (cache_name_pos(pathname, len) >= 0) + if (cache_name_exists(pathname, len)) return NULL; ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc); @@@ -391,7 -416,7 +416,7 @@@ static enum exist_status directory_exis break; if (endchar == '/') return index_directory; - if (!endchar && S_ISGITLINK(ntohl(ce->ce_mode))) + if (!endchar && S_ISGITLINK(ce->ce_mode)) return index_gitdir; } return index_nonexistent; @@@ -508,7 -533,7 +533,7 @@@ static int in_pathspec(const char *path static int get_dtype(struct dirent *de, const char *path) { - int dtype = DTYPE(de); + int dtype = de ? DTYPE(de) : DT_UNKNOWN; struct stat st; if (dtype != DT_UNKNOWN) @@@ -560,7 -585,8 +585,8 @@@ static int read_directory_recursive(str if (simplify_away(fullname, baselen + len, simplify)) continue; - exclude = excluded(dir, fullname); + dtype = DTYPE(de); + exclude = excluded(dir, fullname, &dtype); if (exclude && dir->collect_ignored && in_pathspec(fullname, baselen + len, simplify)) dir_add_ignored(dir, fullname, baselen + len); @@@ -572,7 -598,8 +598,8 @@@ if (exclude && !dir->show_ignored) continue; - dtype = get_dtype(de, fullname); + if (dtype == DT_UNKNOWN) + dtype = get_dtype(de, fullname); /* * Do we want to see just the ignored files? diff --combined unpack-trees.c index ff46fd62fd,29848e926c..ec558f9005 --- a/unpack-trees.c +++ b/unpack-trees.c @@@ -289,6 -289,7 +289,6 @@@ static struct checkout state static void check_updates(struct cache_entry **src, int nr, struct unpack_trees_options *o) { - unsigned short mask = htons(CE_UPDATE); unsigned cnt = 0, total = 0; struct progress *progress = NULL; char last_symlink[PATH_MAX]; @@@ -296,7 -297,7 +296,7 @@@ if (o->update && o->verbose_update) { for (total = cnt = 0; cnt < nr; cnt++) { struct cache_entry *ce = src[cnt]; - if (!ce->ce_mode || ce->ce_flags & mask) + if (ce->ce_flags & (CE_UPDATE | CE_REMOVE)) total++; } @@@ -309,15 -310,15 +309,15 @@@ while (nr--) { struct cache_entry *ce = *src++; - if (!ce->ce_mode || ce->ce_flags & mask) + if (ce->ce_flags & (CE_UPDATE | CE_REMOVE)) display_progress(progress, ++cnt); - if (!ce->ce_mode) { + if (ce->ce_flags & CE_REMOVE) { if (o->update) unlink_entry(ce->name, last_symlink); continue; } - if (ce->ce_flags & mask) { - ce->ce_flags &= ~mask; + if (ce->ce_flags & CE_UPDATE) { + ce->ce_flags &= ~CE_UPDATE; if (o->update) { checkout_entry(ce, &state, NULL); *last_symlink = '\0'; @@@ -407,7 -408,7 +407,7 @@@ static void verify_uptodate(struct cach * submodules that are marked to be automatically * checked out. */ - if (S_ISGITLINK(ntohl(ce->ce_mode))) + if (S_ISGITLINK(ce->ce_mode)) return; errno = 0; } @@@ -449,7 -450,7 +449,7 @@@ static int verify_clean_subdirectory(st int cnt = 0; unsigned char sha1[20]; - if (S_ISGITLINK(ntohl(ce->ce_mode)) && + if (S_ISGITLINK(ce->ce_mode) && resolve_gitlink_ref(ce->name, "HEAD", sha1) == 0) { /* If we are not going to update the submodule, then * we don't care. @@@ -480,7 -481,7 +480,7 @@@ */ if (!ce_stage(ce)) { verify_uptodate(ce, o); - ce->ce_mode = 0; + ce->ce_flags |= CE_REMOVE; } cnt++; } @@@ -521,8 -522,9 +521,9 @@@ static void verify_absent(struct cache_ if (!lstat(ce->name, &st)) { int cnt; + int dtype = ce_to_dtype(ce); - if (o->dir && excluded(o->dir, ce->name)) + if (o->dir && excluded(o->dir, ce->name, &dtype)) /* * ce->name is explicitly excluded, so it is Ok to * overwrite it. @@@ -567,7 -569,7 +568,7 @@@ cnt = cache_name_pos(ce->name, strlen(ce->name)); if (0 <= cnt) { struct cache_entry *ce = active_cache[cnt]; - if (!ce_stage(ce) && !ce->ce_mode) + if (ce->ce_flags & CE_REMOVE) return; } @@@ -579,7 -581,7 +580,7 @@@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old, struct unpack_trees_options *o) { - merge->ce_flags |= htons(CE_UPDATE); + merge->ce_flags |= CE_UPDATE; if (old) { /* * See if we can re-use the old CE directly? @@@ -600,7 -602,7 +601,7 @@@ invalidate_ce_path(merge); } - merge->ce_flags &= ~htons(CE_STAGEMASK); + merge->ce_flags &= ~CE_STAGEMASK; add_cache_entry(merge, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); return 1; } @@@ -612,7 -614,7 +613,7 @@@ static int deleted_entry(struct cache_e verify_uptodate(old, o); else verify_absent(ce, "removed", o); - ce->ce_mode = 0; + ce->ce_flags |= CE_REMOVE; add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); invalidate_ce_path(ce); return 1; @@@ -633,7 -635,7 +634,7 @@@ static void show_stage_entry(FILE *o else fprintf(o, "%s%06o %s %d\t%s\n", label, - ntohl(ce->ce_mode), + ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce), ce->name); @@@ -919,7 -921,7 +920,7 @@@ int oneway_merge(struct cache_entry **s struct stat st; if (lstat(old->name, &st) || ce_match_stat(old, &st, CE_MATCH_IGNORE_VALID)) - old->ce_flags |= htons(CE_UPDATE); + old->ce_flags |= CE_UPDATE; } return keep_entry(old, o); }