commit ac5f2b268fa7b1547b452a2d2234c03a33a1edf6 from: Stefan Sperling date: Tue May 05 15:26:11 2020 UTC normalize file mode bits to avoid false positive tree entry differences commit - 0208f208304c36921fbcd86d33751b877aab1e96 commit + ac5f2b268fa7b1547b452a2d2234c03a33a1edf6 blob - ea5232abfd828a7f52894757aaa990fca8c07c9b blob + 60884259fffeeadac52f16b3ef8d210656e4c539 --- lib/object.c +++ lib/object.c @@ -1622,6 +1622,25 @@ done: if (tree) got_object_tree_close(tree); return err; +} + +/* + * Normalize file mode bits to avoid false positive tree entry differences + * in case tree entries have unexpected mode bits set. + */ +static mode_t +normalize_mode_for_comparison(mode_t mode) +{ + /* + * For directories, the only relevant bit is the IFDIR bit. + * This allows us to detect paths changing from a directory + * to a file and vice versa. + */ + if (S_ISDIR(mode)) + return mode & S_IFDIR; + + /* For files, the only change we care about is the executable bit. */ + return mode & S_IXUSR; } const struct got_error * @@ -1650,6 +1669,7 @@ got_object_tree_path_changed(int *changed, seglen = 0; while (*s) { struct got_tree_object *next_tree1, *next_tree2; + mode_t mode1, mode2; if (*s != '/') { s++; @@ -1670,7 +1690,9 @@ got_object_tree_path_changed(int *changed, goto done; } - if (te1->mode != te2->mode) { + mode1 = normalize_mode_for_comparison(te1->mode); + mode2 = normalize_mode_for_comparison(te2->mode); + if (mode1 != mode2) { *changed = 1; goto done; }