Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 89a75ef

Browse files
tfarinaevmar
authored andcommitted
Move CanonicalizePath into util.h so it can be shared by the other modules.
Also add util_test.cc and move the CanonicalizePathTest into there. Signed-off-by: Thiago Farina <tfarina@chromium.org>
1 parent 343c526 commit 89a75ef

File tree

7 files changed

+117
-89
lines changed

7 files changed

+117
-89
lines changed

build.ninja

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ build $builddir/ninja_test.o: cxx src/ninja_test.cc
6363
build $builddir/parsers_test.o: cxx src/parsers_test.cc
6464
build $builddir/subprocess_test.o: cxx src/subprocess_test.cc
6565
build $builddir/test.o: cxx src/test.cc
66+
build $builddir/util_test.o: cxx src/util_test.cc
6667
build ninja_test: link $builddir/build_test.o $builddir/build_log_test.o \
6768
$builddir/graph_test.o $builddir/ninja_test.o $builddir/parsers_test.o \
6869
$builddir/subprocess_test.o $builddir/test.o $builddir/ninja.a

src/graph.cc

+1-53
Original file line numberDiff line numberDiff line change
@@ -19,59 +19,7 @@
1919
#include "build_log.h"
2020
#include "ninja.h"
2121
#include "parsers.h"
22-
23-
// Canonicalize a path like "foo/../bar.h" into just "bar.h".
24-
bool CanonicalizePath(string* path, string* err) {
25-
// Try to fast-path out the common case.
26-
if (path->find("/.") == string::npos &&
27-
path->find("./") == string::npos) {
28-
return true;
29-
}
30-
31-
string inpath = *path;
32-
vector<const char*> parts;
33-
for (string::size_type start = 0; start < inpath.size(); ++start) {
34-
string::size_type end = inpath.find('/', start);
35-
if (end == string::npos)
36-
end = inpath.size();
37-
else
38-
inpath[end] = 0;
39-
parts.push_back(inpath.data() + start);
40-
start = end;
41-
}
42-
43-
vector<const char*>::iterator i = parts.begin();
44-
while (i != parts.end()) {
45-
const char* part = *i;
46-
if (part[0] == '.') {
47-
if (part[1] == 0) {
48-
// "."; strip.
49-
parts.erase(i);
50-
continue;
51-
} else if (part[1] == '.' && part[2] == 0) {
52-
// ".."; go up one.
53-
if (i == parts.begin()) {
54-
*err = "can't canonicalize path '" + *path + "' that reaches "
55-
"above its directory";
56-
return false;
57-
}
58-
--i;
59-
parts.erase(i, i + 2);
60-
continue;
61-
}
62-
}
63-
++i;
64-
}
65-
path->clear();
66-
67-
for (i = parts.begin(); i != parts.end(); ++i) {
68-
if (!path->empty())
69-
path->push_back('/');
70-
path->append(*i);
71-
}
72-
73-
return true;
74-
}
22+
#include "util.h"
7523

7624
bool FileStat::Stat(DiskInterface* disk_interface) {
7725
mtime_ = disk_interface->Stat(path_);

src/graph.h

-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,4 @@ struct Edge {
119119
bool is_phony() const;
120120
};
121121

122-
// Exposed for testing.
123-
bool CanonicalizePath(string* path, string* err);
124-
125122
#endif // NINJA_GRAPH_H_

src/graph_test.cc

-33
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,6 @@
1616

1717
#include "test.h"
1818

19-
TEST(CanonicalizePath, PathSamples) {
20-
string path = "foo.h";
21-
string err;
22-
EXPECT_TRUE(CanonicalizePath(&path, &err));
23-
EXPECT_EQ("", err);
24-
EXPECT_EQ("foo.h", path);
25-
26-
path = "./foo.h"; err = "";
27-
EXPECT_TRUE(CanonicalizePath(&path, &err));
28-
EXPECT_EQ("", err);
29-
EXPECT_EQ("foo.h", path);
30-
31-
path = "./foo/./bar.h"; err = "";
32-
EXPECT_TRUE(CanonicalizePath(&path, &err));
33-
EXPECT_EQ("", err);
34-
EXPECT_EQ("foo/bar.h", path);
35-
36-
path = "./x/foo/../bar.h"; err = "";
37-
EXPECT_TRUE(CanonicalizePath(&path, &err));
38-
EXPECT_EQ("", err);
39-
EXPECT_EQ("x/bar.h", path);
40-
41-
path = "./x/foo/../../bar.h"; err = "";
42-
EXPECT_TRUE(CanonicalizePath(&path, &err));
43-
EXPECT_EQ("", err);
44-
EXPECT_EQ("bar.h", path);
45-
46-
path = "./x/../foo/../../bar.h"; err = "";
47-
EXPECT_FALSE(CanonicalizePath(&path, &err));
48-
EXPECT_EQ("can't canonicalize path './x/../foo/../../bar.h' that reaches "
49-
"above its directory", err);
50-
}
51-
5219
struct GraphTest : public StateTestWithBuiltinRules {
5320
VirtualFileSystem fs_;
5421
};

src/util.cc

+54
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <stdio.h>
1919
#include <stdlib.h>
2020

21+
#include <vector>
22+
2123
void Fatal(const char* msg, ...) {
2224
va_list ap;
2325
fprintf(stderr, "FATAL: ");
@@ -27,3 +29,55 @@ void Fatal(const char* msg, ...) {
2729
fprintf(stderr, "\n");
2830
exit(1);
2931
}
32+
33+
bool CanonicalizePath(std::string* path, std::string* err) {
34+
// Try to fast-path out the common case.
35+
if (path->find("/.") == std::string::npos &&
36+
path->find("./") == std::string::npos) {
37+
return true;
38+
}
39+
40+
std::string inpath = *path;
41+
std::vector<const char*> parts;
42+
for (std::string::size_type start = 0; start < inpath.size(); ++start) {
43+
std::string::size_type end = inpath.find('/', start);
44+
if (end == std::string::npos)
45+
end = inpath.size();
46+
else
47+
inpath[end] = 0;
48+
parts.push_back(inpath.data() + start);
49+
start = end;
50+
}
51+
52+
std::vector<const char*>::iterator i = parts.begin();
53+
while (i != parts.end()) {
54+
const char* part = *i;
55+
if (part[0] == '.') {
56+
if (part[1] == 0) {
57+
// "."; strip.
58+
parts.erase(i);
59+
continue;
60+
} else if (part[1] == '.' && part[2] == 0) {
61+
// ".."; go up one.
62+
if (i == parts.begin()) {
63+
*err = "can't canonicalize path '" + *path + "' that reaches "
64+
"above its directory";
65+
return false;
66+
}
67+
--i;
68+
parts.erase(i, i + 2);
69+
continue;
70+
}
71+
}
72+
++i;
73+
}
74+
path->clear();
75+
76+
for (i = parts.begin(); i != parts.end(); ++i) {
77+
if (!path->empty())
78+
path->push_back('/');
79+
path->append(*i);
80+
}
81+
82+
return true;
83+
}

src/util.h

+11
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,21 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#ifndef NINJA_UTIL_H_
16+
#define NINJA_UTIL_H_
17+
#pragma once
18+
19+
#include <string>
20+
1521
// Dump a backtrace to stderr.
1622
// |skip_frames| is how many frames to skip;
1723
// DumpBacktrace implicitly skips itself already.
1824
void DumpBacktrace(int skip_frames);
1925

2026
// Log a fatal message, dump a backtrace, and exit.
2127
void Fatal(const char* msg, ...);
28+
29+
// Canonicalize a path like "foo/../bar.h" into just "bar.h".
30+
bool CanonicalizePath(std::string* path, std::string* err);
31+
32+
#endif // NINJA_UTIL_H_

src/util_test.cc

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2011 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "util.h"
16+
17+
#include "test.h"
18+
19+
TEST(CanonicalizePath, PathSamples) {
20+
std::string path = "foo.h";
21+
std::string err;
22+
EXPECT_TRUE(CanonicalizePath(&path, &err));
23+
EXPECT_EQ("", err);
24+
EXPECT_EQ("foo.h", path);
25+
26+
path = "./foo.h"; err = "";
27+
EXPECT_TRUE(CanonicalizePath(&path, &err));
28+
EXPECT_EQ("", err);
29+
EXPECT_EQ("foo.h", path);
30+
31+
path = "./foo/./bar.h"; err = "";
32+
EXPECT_TRUE(CanonicalizePath(&path, &err));
33+
EXPECT_EQ("", err);
34+
EXPECT_EQ("foo/bar.h", path);
35+
36+
path = "./x/foo/../bar.h"; err = "";
37+
EXPECT_TRUE(CanonicalizePath(&path, &err));
38+
EXPECT_EQ("", err);
39+
EXPECT_EQ("x/bar.h", path);
40+
41+
path = "./x/foo/../../bar.h"; err = "";
42+
EXPECT_TRUE(CanonicalizePath(&path, &err));
43+
EXPECT_EQ("", err);
44+
EXPECT_EQ("bar.h", path);
45+
46+
path = "./x/../foo/../../bar.h"; err = "";
47+
EXPECT_FALSE(CanonicalizePath(&path, &err));
48+
EXPECT_EQ("can't canonicalize path './x/../foo/../../bar.h' that reaches "
49+
"above its directory", err);
50+
}

0 commit comments

Comments
 (0)