@matheusbsbs / matheus-bagliano / commits / ae299be0e5
Fork 0

Implement normalize_absolute_path

normalize_absolute_path removes several oddities form absolute paths, giving nice clean paths like "/dir/sub1/sub2". Also add a test case for this utility, based on a new test program (in the style of test-sha1). Signed-off-by: David Reiss <dreiss@facebook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Reiss committed May 19, 2008 at 23:48 UTC ae299be0e5e610027e6492d48d70c1cbb0e9edd8
6 files changed +109 -1
.gitignore
+1
@@ -150,6 +150,7 @@ test-dump-cache-tree
150 test-genrandom
151 test-match-trees
152 test-parse-options
153 +test-path-utils
154 test-sha1
155 common-cmds.h
156 *.tar.gz
Makefile
+1 -1
@@ -1186,7 +1186,7 @@ endif
1186
1187 ### Testing rules
1188
1189 -TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
1189 +TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X test-path-utils$X
1190
1191 all:: $(TEST_PROGRAMS)
1192
cache.h
+1
@@ -514,6 +514,7 @@ static inline int is_absolute_path(const char *path)
514 return path[0] == '/';
515 }
516 const char *make_absolute_path(const char *path);
517 +int normalize_absolute_path(char *buf, const char *path);
518
519 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
520 extern int sha1_object_info(const unsigned char *, unsigned long *);
path.c
+53
@@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path)
357
358 return buf;
359 }
360 +
361 +/*
362 + * path = absolute path
363 + * buf = buffer of at least max(2, strlen(path)+1) bytes
364 + * It is okay if buf == path, but they should not overlap otherwise.
365 + *
366 + * Performs the following normalizations on path, storing the result in buf:
367 + * - Removes trailing slashes.
368 + * - Removes empty components.
369 + * - Removes "." components.
370 + * - Removes ".." components, and the components the precede them.
371 + * "" and paths that contain only slashes are normalized to "/".
372 + * Returns the length of the output.
373 + *
374 + * Note that this function is purely textual. It does not follow symlinks,
375 + * verify the existence of the path, or make any system calls.
376 + */
377 +int normalize_absolute_path(char *buf, const char *path)
378 +{
379 + const char *comp_start = path, *comp_end = path;
380 + char *dst = buf;
381 + int comp_len;
382 + assert(buf);
383 + assert(path);
384 +
385 + while (*comp_start) {
386 + assert(*comp_start == '/');
387 + while (*++comp_end && *comp_end != '/')
388 + ; /* nothing */
389 + comp_len = comp_end - comp_start;
390 +
391 + if (!strncmp("/", comp_start, comp_len) ||
392 + !strncmp("/.", comp_start, comp_len))
393 + goto next;
394 +
395 + if (!strncmp("/..", comp_start, comp_len)) {
396 + while (dst > buf && *--dst != '/')
397 + ; /* nothing */
398 + goto next;
399 + }
400 +
401 + memcpy(dst, comp_start, comp_len);
402 + dst += comp_len;
403 + next:
404 + comp_start = comp_end;
405 + }
406 +
407 + if (dst == buf)
408 + *dst++ = '/';
409 +
410 + *dst = '\0';
411 + return dst - buf;
412 +}
t/t0060-path-utils.sh new
+40
@@ -0,0 +1,40 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2008 David Reiss
4 +#
5 +
6 +test_description='Test various path utilities'
7 +
8 +. ./test-lib.sh
9 +
10 +norm_abs() {
11 + test_expect_success "normalize absolute" \
12 + "test \$(test-path-utils normalize_absolute_path '$1') = '$2'"
13 +}
14 +
15 +norm_abs "" /
16 +norm_abs / /
17 +norm_abs // /
18 +norm_abs /// /
19 +norm_abs /. /
20 +norm_abs /./ /
21 +norm_abs /./.. /
22 +norm_abs /../. /
23 +norm_abs /./../.// /
24 +norm_abs /dir/.. /
25 +norm_abs /dir/sub/../.. /
26 +norm_abs /dir /dir
27 +norm_abs /dir// /dir
28 +norm_abs /./dir /dir
29 +norm_abs /dir/. /dir
30 +norm_abs /dir///./ /dir
31 +norm_abs /dir//sub/.. /dir
32 +norm_abs /dir/sub/../ /dir
33 +norm_abs //dir/sub/../. /dir
34 +norm_abs /dir/s1/../s2/ /dir/s2
35 +norm_abs /d1/s1///s2/..//../s3/ /d1/s3
36 +norm_abs /d1/s1//../s2/../../d2 /d2
37 +norm_abs /d1/.../d2 /d1/.../d2
38 +norm_abs /d1/..././../d2 /d1/d2
39 +
40 +test_done
test-path-utils.c new
+13
@@ -0,0 +1,13 @@
1 +#include "cache.h"
2 +
3 +int main(int argc, char **argv)
4 +{
5 + if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
6 + char *buf = xmalloc(strlen(argv[2])+1);
7 + int rv = normalize_absolute_path(buf, argv[2]);
8 + assert(strlen(buf) == rv);
9 + puts(buf);
10 + }
11 +
12 + return 0;
13 +}