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>
This commit is contained in:
parent
377d9c409f
commit
ae299be0e5
1
.gitignore
vendored
1
.gitignore
vendored
@ -150,6 +150,7 @@ test-dump-cache-tree
|
|||||||
test-genrandom
|
test-genrandom
|
||||||
test-match-trees
|
test-match-trees
|
||||||
test-parse-options
|
test-parse-options
|
||||||
|
test-path-utils
|
||||||
test-sha1
|
test-sha1
|
||||||
common-cmds.h
|
common-cmds.h
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
2
Makefile
2
Makefile
@ -1186,7 +1186,7 @@ endif
|
|||||||
|
|
||||||
### Testing rules
|
### Testing rules
|
||||||
|
|
||||||
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_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
|
||||||
|
|
||||||
all:: $(TEST_PROGRAMS)
|
all:: $(TEST_PROGRAMS)
|
||||||
|
|
||||||
|
1
cache.h
1
cache.h
@ -514,6 +514,7 @@ static inline int is_absolute_path(const char *path)
|
|||||||
return path[0] == '/';
|
return path[0] == '/';
|
||||||
}
|
}
|
||||||
const char *make_absolute_path(const char *path);
|
const char *make_absolute_path(const char *path);
|
||||||
|
int normalize_absolute_path(char *buf, const char *path);
|
||||||
|
|
||||||
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
||||||
extern int sha1_object_info(const unsigned char *, unsigned long *);
|
extern int sha1_object_info(const unsigned char *, unsigned long *);
|
||||||
|
53
path.c
53
path.c
@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path)
|
|||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* path = absolute path
|
||||||
|
* buf = buffer of at least max(2, strlen(path)+1) bytes
|
||||||
|
* It is okay if buf == path, but they should not overlap otherwise.
|
||||||
|
*
|
||||||
|
* Performs the following normalizations on path, storing the result in buf:
|
||||||
|
* - Removes trailing slashes.
|
||||||
|
* - Removes empty components.
|
||||||
|
* - Removes "." components.
|
||||||
|
* - Removes ".." components, and the components the precede them.
|
||||||
|
* "" and paths that contain only slashes are normalized to "/".
|
||||||
|
* Returns the length of the output.
|
||||||
|
*
|
||||||
|
* Note that this function is purely textual. It does not follow symlinks,
|
||||||
|
* verify the existence of the path, or make any system calls.
|
||||||
|
*/
|
||||||
|
int normalize_absolute_path(char *buf, const char *path)
|
||||||
|
{
|
||||||
|
const char *comp_start = path, *comp_end = path;
|
||||||
|
char *dst = buf;
|
||||||
|
int comp_len;
|
||||||
|
assert(buf);
|
||||||
|
assert(path);
|
||||||
|
|
||||||
|
while (*comp_start) {
|
||||||
|
assert(*comp_start == '/');
|
||||||
|
while (*++comp_end && *comp_end != '/')
|
||||||
|
; /* nothing */
|
||||||
|
comp_len = comp_end - comp_start;
|
||||||
|
|
||||||
|
if (!strncmp("/", comp_start, comp_len) ||
|
||||||
|
!strncmp("/.", comp_start, comp_len))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (!strncmp("/..", comp_start, comp_len)) {
|
||||||
|
while (dst > buf && *--dst != '/')
|
||||||
|
; /* nothing */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dst, comp_start, comp_len);
|
||||||
|
dst += comp_len;
|
||||||
|
next:
|
||||||
|
comp_start = comp_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst == buf)
|
||||||
|
*dst++ = '/';
|
||||||
|
|
||||||
|
*dst = '\0';
|
||||||
|
return dst - buf;
|
||||||
|
}
|
||||||
|
40
t/t0060-path-utils.sh
Executable file
40
t/t0060-path-utils.sh
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 David Reiss
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='Test various path utilities'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
norm_abs() {
|
||||||
|
test_expect_success "normalize absolute" \
|
||||||
|
"test \$(test-path-utils normalize_absolute_path '$1') = '$2'"
|
||||||
|
}
|
||||||
|
|
||||||
|
norm_abs "" /
|
||||||
|
norm_abs / /
|
||||||
|
norm_abs // /
|
||||||
|
norm_abs /// /
|
||||||
|
norm_abs /. /
|
||||||
|
norm_abs /./ /
|
||||||
|
norm_abs /./.. /
|
||||||
|
norm_abs /../. /
|
||||||
|
norm_abs /./../.// /
|
||||||
|
norm_abs /dir/.. /
|
||||||
|
norm_abs /dir/sub/../.. /
|
||||||
|
norm_abs /dir /dir
|
||||||
|
norm_abs /dir// /dir
|
||||||
|
norm_abs /./dir /dir
|
||||||
|
norm_abs /dir/. /dir
|
||||||
|
norm_abs /dir///./ /dir
|
||||||
|
norm_abs /dir//sub/.. /dir
|
||||||
|
norm_abs /dir/sub/../ /dir
|
||||||
|
norm_abs //dir/sub/../. /dir
|
||||||
|
norm_abs /dir/s1/../s2/ /dir/s2
|
||||||
|
norm_abs /d1/s1///s2/..//../s3/ /d1/s3
|
||||||
|
norm_abs /d1/s1//../s2/../../d2 /d2
|
||||||
|
norm_abs /d1/.../d2 /d1/.../d2
|
||||||
|
norm_abs /d1/..././../d2 /d1/d2
|
||||||
|
|
||||||
|
test_done
|
13
test-path-utils.c
Normal file
13
test-path-utils.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "cache.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
|
||||||
|
char *buf = xmalloc(strlen(argv[2])+1);
|
||||||
|
int rv = normalize_absolute_path(buf, argv[2]);
|
||||||
|
assert(strlen(buf) == rv);
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user