Browse Source

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>
maint
David Reiss 17 years ago committed by Junio C Hamano
parent
commit
ae299be0e5
  1. 1
      .gitignore
  2. 2
      Makefile
  3. 1
      cache.h
  4. 53
      path.c
  5. 40
      t/t0060-path-utils.sh
  6. 13
      test-path-utils.c

1
.gitignore vendored

@ -150,6 +150,7 @@ test-dump-cache-tree @@ -150,6 +150,7 @@ test-dump-cache-tree
test-genrandom
test-match-trees
test-parse-options
test-path-utils
test-sha1
common-cmds.h
*.tar.gz

2
Makefile

@ -1186,7 +1186,7 @@ endif @@ -1186,7 +1186,7 @@ endif

### 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)


1
cache.h

@ -514,6 +514,7 @@ static inline int is_absolute_path(const char *path) @@ -514,6 +514,7 @@ static inline int is_absolute_path(const char *path)
return path[0] == '/';
}
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 */
extern int sha1_object_info(const unsigned char *, unsigned long *);

53
path.c

@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path) @@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path)

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

@ -0,0 +1,40 @@ @@ -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

@ -0,0 +1,13 @@ @@ -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…
Cancel
Save