Skip to content

Commit f3cad0a

Browse files
j6tgitster
authored andcommitted
Move sanitary_path_copy() to path.c and rename it to normalize_path_copy()
This function and normalize_absolute_path() do almost the same thing. The former already works on Windows, but the latter crashes. In subsequent changes we will remove normalize_absolute_path(). Here we make the replacement function reusable. On the way we rename it to reflect that it does some path normalization. Apart from that this is only moving around code. Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2cd85c4 commit f3cad0a

File tree

3 files changed

+88
-87
lines changed

3 files changed

+88
-87
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ const char *make_absolute_path(const char *path);
548548
const char *make_nonrelative_path(const char *path);
549549
const char *make_relative_path(const char *abs, const char *base);
550550
int normalize_absolute_path(char *buf, const char *path);
551+
int normalize_path_copy(char *dst, const char *src);
551552
int longest_ancestor_length(const char *path, const char *prefix_list);
552553

553554
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */

path.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,92 @@ int normalize_absolute_path(char *buf, const char *path)
415415
return dst - buf;
416416
}
417417

418+
int normalize_path_copy(char *dst, const char *src)
419+
{
420+
char *dst0;
421+
422+
if (has_dos_drive_prefix(src)) {
423+
*dst++ = *src++;
424+
*dst++ = *src++;
425+
}
426+
dst0 = dst;
427+
428+
if (is_dir_sep(*src)) {
429+
*dst++ = '/';
430+
while (is_dir_sep(*src))
431+
src++;
432+
}
433+
434+
for (;;) {
435+
char c = *src;
436+
437+
/*
438+
* A path component that begins with . could be
439+
* special:
440+
* (1) "." and ends -- ignore and terminate.
441+
* (2) "./" -- ignore them, eat slash and continue.
442+
* (3) ".." and ends -- strip one and terminate.
443+
* (4) "../" -- strip one, eat slash and continue.
444+
*/
445+
if (c == '.') {
446+
if (!src[1]) {
447+
/* (1) */
448+
src++;
449+
} else if (is_dir_sep(src[1])) {
450+
/* (2) */
451+
src += 2;
452+
while (is_dir_sep(*src))
453+
src++;
454+
continue;
455+
} else if (src[1] == '.') {
456+
if (!src[2]) {
457+
/* (3) */
458+
src += 2;
459+
goto up_one;
460+
} else if (is_dir_sep(src[2])) {
461+
/* (4) */
462+
src += 3;
463+
while (is_dir_sep(*src))
464+
src++;
465+
goto up_one;
466+
}
467+
}
468+
}
469+
470+
/* copy up to the next '/', and eat all '/' */
471+
while ((c = *src++) != '\0' && !is_dir_sep(c))
472+
*dst++ = c;
473+
if (is_dir_sep(c)) {
474+
*dst++ = '/';
475+
while (is_dir_sep(c))
476+
c = *src++;
477+
src--;
478+
} else if (!c)
479+
break;
480+
continue;
481+
482+
up_one:
483+
/*
484+
* dst0..dst is prefix portion, and dst[-1] is '/';
485+
* go up one level.
486+
*/
487+
dst -= 2; /* go past trailing '/' if any */
488+
if (dst < dst0)
489+
return -1;
490+
while (1) {
491+
if (dst <= dst0)
492+
break;
493+
c = *dst--;
494+
if (c == '/') { /* MinGW: cannot be '\\' anymore */
495+
dst += 2;
496+
break;
497+
}
498+
}
499+
}
500+
*dst = '\0';
501+
return 0;
502+
}
503+
418504
/*
419505
* path = Canonical absolute path
420506
* prefix_list = Colon-separated list of absolute paths

setup.c

Lines changed: 1 addition & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,92 +4,6 @@
44
static int inside_git_dir = -1;
55
static int inside_work_tree = -1;
66

7-
static int sanitary_path_copy(char *dst, const char *src)
8-
{
9-
char *dst0;
10-
11-
if (has_dos_drive_prefix(src)) {
12-
*dst++ = *src++;
13-
*dst++ = *src++;
14-
}
15-
dst0 = dst;
16-
17-
if (is_dir_sep(*src)) {
18-
*dst++ = '/';
19-
while (is_dir_sep(*src))
20-
src++;
21-
}
22-
23-
for (;;) {
24-
char c = *src;
25-
26-
/*
27-
* A path component that begins with . could be
28-
* special:
29-
* (1) "." and ends -- ignore and terminate.
30-
* (2) "./" -- ignore them, eat slash and continue.
31-
* (3) ".." and ends -- strip one and terminate.
32-
* (4) "../" -- strip one, eat slash and continue.
33-
*/
34-
if (c == '.') {
35-
if (!src[1]) {
36-
/* (1) */
37-
src++;
38-
} else if (is_dir_sep(src[1])) {
39-
/* (2) */
40-
src += 2;
41-
while (is_dir_sep(*src))
42-
src++;
43-
continue;
44-
} else if (src[1] == '.') {
45-
if (!src[2]) {
46-
/* (3) */
47-
src += 2;
48-
goto up_one;
49-
} else if (is_dir_sep(src[2])) {
50-
/* (4) */
51-
src += 3;
52-
while (is_dir_sep(*src))
53-
src++;
54-
goto up_one;
55-
}
56-
}
57-
}
58-
59-
/* copy up to the next '/', and eat all '/' */
60-
while ((c = *src++) != '\0' && !is_dir_sep(c))
61-
*dst++ = c;
62-
if (is_dir_sep(c)) {
63-
*dst++ = '/';
64-
while (is_dir_sep(c))
65-
c = *src++;
66-
src--;
67-
} else if (!c)
68-
break;
69-
continue;
70-
71-
up_one:
72-
/*
73-
* dst0..dst is prefix portion, and dst[-1] is '/';
74-
* go up one level.
75-
*/
76-
dst -= 2; /* go past trailing '/' if any */
77-
if (dst < dst0)
78-
return -1;
79-
while (1) {
80-
if (dst <= dst0)
81-
break;
82-
c = *dst--;
83-
if (c == '/') { /* MinGW: cannot be '\\' anymore */
84-
dst += 2;
85-
break;
86-
}
87-
}
88-
}
89-
*dst = '\0';
90-
return 0;
91-
}
92-
937
const char *prefix_path(const char *prefix, int len, const char *path)
948
{
959
const char *orig = path;
@@ -101,7 +15,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
10115
memcpy(sanitized, prefix, len);
10216
strcpy(sanitized + len, path);
10317
}
104-
if (sanitary_path_copy(sanitized, sanitized))
18+
if (normalize_path_copy(sanitized, sanitized))
10519
goto error_out;
10620
if (is_absolute_path(orig)) {
10721
const char *work_tree = get_git_work_tree();

0 commit comments

Comments
 (0)