aboutsummaryrefslogtreecommitdiffstats
path: root/dir.h
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2020-08-18 22:58:26 +0000
committerJunio C Hamano <gitster@pobox.com>2020-08-18 17:17:31 -0700
commiteceba5321410bbcc9e0b11e6aa479832f574eca8 (patch)
treecd31d4f411acc27ef42499dc5331c683fe022a90 /dir.h
parentdad4f23ce59339bb32ad9e1cc1682c696f7a724f (diff)
downloadgit-eceba5321410bbcc9e0b11e6aa479832f574eca8.tar.gz
dir: fix problematic API to avoid memory leaks
The dir structure seemed to have a number of leaks and problems around it. First I noticed that parent_hashmap and recursive_hashmap were being leaked (though Peff noticed and submitted fixes before me). Then I noticed in the previous commit that clear_directory() was only taking responsibility for a subset of fields within dir_struct, despite the fact that entries[] and ignored[] we allocated internally to dir.c. That, of course, resulted in many callers either leaking or haphazardly trying to free these arrays and their contents. Digging further, I found that despite the pretty clear documentation near the top of dir.h that folks were supposed to call clear_directory() when the user no longer needed the dir_struct, there were four callers that didn't bother doing that at all. However, two of them clearly thought about leaks since they had an UNLEAK(dir) directive, which to me suggests that the method to free the data was too unclear. I suspect the non-obviousness of the API and its holes led folks to avoid it, which then snowballed into further problems with the entries[], ignored[], parent_hashmap, and recursive_hashmap problems. Rename clear_directory() to dir_clear() to be more in line with other data structures in git, and introduce a dir_init() to handle the suggested memsetting of dir_struct to all zeroes. I hope that a name like "dir_clear()" is more clear, and that the presence of dir_init() will provide a hint to those looking at the code that they need to look for either a dir_clear() or a dir_free() and lead them to find dir_clear(). Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir.h')
-rw-r--r--dir.h21
1 files changed, 11 insertions, 10 deletions
diff --git a/dir.h b/dir.h
index 7d76d0644f..a3c40dec51 100644
--- a/dir.h
+++ b/dir.h
@@ -19,24 +19,23 @@
* CE_SKIP_WORKTREE marked. If you want to exclude files, make sure you have
* loaded the index first.
*
- * - Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
- * sizeof(dir))`.
+ * - Prepare `struct dir_struct dir` using `dir_init()` function.
*
* - To add single exclude pattern, call `add_pattern_list()` and then
* `add_pattern()`.
*
* - To add patterns from a file (e.g. `.git/info/exclude`), call
- * `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. A
- * short-hand function `setup_standard_excludes()` can be used to set
- * up the standard set of exclude settings.
+ * `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`.
*
- * - Set options described in the Data Structure section above.
+ * - A short-hand function `setup_standard_excludes()` can be used to set
+ * up the standard set of exclude settings, instead of manually calling
+ * the add_pattern*() family of functions.
*
- * - Call `read_directory()`.
+ * - Call `fill_directory()`.
*
- * - Use `dir.entries[]`.
+ * - Use `dir.entries[]` and `dir.ignored[]`.
*
- * - Call `clear_directory()` when the contained elements are no longer in use.
+ * - Call `dir_clear()` when the contained elements are no longer in use.
*
*/
@@ -362,6 +361,8 @@ int match_pathspec(const struct index_state *istate,
int report_path_error(const char *ps_matched, const struct pathspec *pathspec);
int within_depth(const char *name, int namelen, int depth, int max_depth);
+void dir_init(struct dir_struct *dir);
+
int fill_directory(struct dir_struct *dir,
struct index_state *istate,
const struct pathspec *pathspec);
@@ -428,7 +429,7 @@ void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, i
void add_pattern(const char *string, const char *base,
int baselen, struct pattern_list *pl, int srcpos);
void clear_pattern_list(struct pattern_list *pl);
-void clear_directory(struct dir_struct *dir);
+void dir_clear(struct dir_struct *dir);
int repo_file_exists(struct repository *repo, const char *path);
int file_exists(const char *);