path: add a function to check for path suffix

We have a function to strip the path suffix from a commit, but we don't have one to check for a path suffix. For a plain filename, we can use basename, but that requires an allocation, since POSIX allows it to modify its argument. Refactor strip_path_suffix into a helper function and a new function, ends_with_path_components, to meet this need. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Aug 25, 2019 at 23:33 UTC ce17feb1b3ecfb0344af9b9111a4b4d313d51d7a
2 files changed +33 -9
path.c
+30 -9
@@ -1221,31 +1221,52 @@ static inline int chomp_trailing_dir_sep(const char *path, int len)
1221 }
1222
1223 /*
1224 - * If path ends with suffix (complete path components), returns the
1225 - * part before suffix (sans trailing directory separators).
1226 - * Otherwise returns NULL.
1224 + * If path ends with suffix (complete path components), returns the offset of
1225 + * the last character in the path before the suffix (sans trailing directory
1226 + * separators), and -1 otherwise.
1227 */
1228 -char *strip_path_suffix(const char *path, const char *suffix)
1228 +static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix)
1229 {
1230 int path_len = strlen(path), suffix_len = strlen(suffix);
1231
1232 while (suffix_len) {
1233 if (!path_len)
1234 - return NULL;
1234 + return -1;
1235
1236 if (is_dir_sep(path[path_len - 1])) {
1237 if (!is_dir_sep(suffix[suffix_len - 1]))
1238 - return NULL;
1238 + return -1;
1239 path_len = chomp_trailing_dir_sep(path, path_len);
1240 suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
1241 }
1242 else if (path[--path_len] != suffix[--suffix_len])
1243 - return NULL;
1243 + return -1;
1244 }
1245
1246 if (path_len && !is_dir_sep(path[path_len - 1]))
1247 - return NULL;
1248 - return xstrndup(path, chomp_trailing_dir_sep(path, path_len));
1247 + return -1;
1248 + return chomp_trailing_dir_sep(path, path_len);
1249 +}
1250 +
1251 +/*
1252 + * Returns true if the path ends with components, considering only complete path
1253 + * components, and false otherwise.
1254 + */
1255 +int ends_with_path_components(const char *path, const char *components)
1256 +{
1257 + return stripped_path_suffix_offset(path, components) != -1;
1258 +}
1259 +
1260 +/*
1261 + * If path ends with suffix (complete path components), returns the
1262 + * part before suffix (sans trailing directory separators).
1263 + * Otherwise returns NULL.
1264 + */
1265 +char *strip_path_suffix(const char *path, const char *suffix)
1266 +{
1267 + ssize_t offset = stripped_path_suffix_offset(path, suffix);
1268 +
1269 + return offset == -1 ? NULL : xstrndup(path, offset);
1270 }
1271
1272 int daemon_avoid_alias(const char *p)
path.h
+3
@@ -193,4 +193,7 @@ const char *git_path_merge_head(struct repository *r);
193 const char *git_path_fetch_head(struct repository *r);
194 const char *git_path_shallow(struct repository *r);
195
196 +
197 +int ends_with_path_components(const char *path, const char *components);
198 +
199 #endif /* PATH_H */