]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/quickbook/src/dependency_tracker.cpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / tools / quickbook / src / dependency_tracker.cpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2013 Daniel James
3
4 Use, modification and distribution is subject to the Boost Software
5 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt)
7=============================================================================*/
8
9#include "dependency_tracker.hpp"
10#include "native_text.hpp"
11#include <boost/filesystem/operations.hpp>
12#include <boost/filesystem/fstream.hpp>
13#include <boost/foreach.hpp>
14
15namespace quickbook
16{
17 // Convert the path to its canonical representation if it exists.
18 // Or something close if it doesn't.
19 static fs::path normalize_path(fs::path const& path)
20 {
21 fs::path p = fs::absolute(path); // The base of the path.
22 fs::path extra; // The non-existant part of the path.
23 int parent_count = 0; // Number of active '..' sections
24
25 // Invariant: path is equivalent to: p / ('..' * parent_count) / extra
26 // i.e. if parent_count == 0: p/extra
27 // if parent_count == 2: p/../../extra
28
29 // Pop path sections from path until we find an existing
30 // path, adjusting for any dot path sections.
31 while (!fs::exists(fs::status(p))) {
32 fs::path name = p.filename();
33 p = p.parent_path();
34 if (name == "..") {
35 ++parent_count;
36 }
37 else if (name == ".") {
38 }
39 else if (parent_count) {
40 --parent_count;
41 }
42 else {
43 extra = name / extra;
44 }
45 }
46
47 // If there are any left over ".." sections, then add them
48 // on to the end of the real path, and trust Boost.Filesystem
49 // to sort them out.
50 while (parent_count) {
51 p = p / "..";
52 --parent_count;
53 }
54
55 // Cannoicalize the existing part of the path, and add 'extra' back to
56 // the end.
57 return fs::canonical(p) / extra;
58 }
59
60 static char const* control_escapes[16] = {
61 "\\000", "\\001", "\\002", "\\003",
62 "\\004", "\\005", "\\006", "\\a",
63 "\\b", "\\t", "\\n", "\\v",
64 "\\f", "\\r", "\\016", "\\017"
65 };
66
67 static std::string escaped_path(std::string const& generic)
68 {
69 std::string result;
70 result.reserve(generic.size());
71
72 BOOST_FOREACH(char c, generic)
73 {
74 if (c >= 0 && c < 16) {
75 result += control_escapes[(unsigned int) c];
76 }
77 else if (c == '\\') {
78 result += "\\\\";
79 }
80 else if (c == 127) {
81 result += "\\177";
82 }
83 else {
84 result += c;
85 }
86 }
87
88 return result;
89 }
90
91 static std::string get_path(fs::path const& path,
92 dependency_tracker::flags f)
93 {
94 std::string generic = quickbook::detail::path_to_generic(path);
95
96 if (f & dependency_tracker::escaped) {
97 generic = escaped_path(generic);
98 }
99
100 return generic;
101 }
102
103 dependency_tracker::dependency_tracker() :
104 dependencies(), glob_dependencies(),
105 last_glob(glob_dependencies.end()) {}
106
107 bool dependency_tracker::add_dependency(fs::path const& f) {
108 bool found = fs::exists(fs::status(f));
109 dependencies[normalize_path(f)] |= found;
110 return found;
111 }
112
113 void dependency_tracker::add_glob(fs::path const& f) {
114 std::pair<glob_list::iterator, bool> r = glob_dependencies.insert(
115 std::make_pair(normalize_path(f), glob_list::mapped_type()));
116 last_glob = r.first;
117 }
118
119 void dependency_tracker::add_glob_match(fs::path const& f) {
120 assert(last_glob != glob_dependencies.end());
121 last_glob->second.insert(normalize_path(f));
122 }
123
124 void dependency_tracker::write_dependencies(fs::path const& file_out,
125 flags f)
126 {
127 fs::ofstream out(file_out);
128
129 if (out.fail()) {
130 throw std::runtime_error(
131 "Error opening dependency file " +
132 quickbook::detail::path_to_generic(file_out));
133 }
134
135 out.exceptions(std::ios::badbit);
136 write_dependencies(out, f);
137 }
138
139 void dependency_tracker::write_dependencies(std::ostream& out,
140 flags f)
141 {
142 if (f & checked) {
143 BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
144 {
145 out << (d.second ? "+ " : "- ")
146 << get_path(d.first, f) << std::endl;
147 }
148
149 BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
150 {
151 out << "g "
152 << get_path(g.first, f) << std::endl;
153
154 BOOST_FOREACH(fs::path const& p, g.second)
155 {
156 out << "+ " << get_path(p, f) << std::endl;
157 }
158 }
159 }
160 else {
161 std::set<std::string> paths;
162
163 BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
164 {
165 if (d.second) {
166 paths.insert(get_path(d.first, f));
167 }
168 }
169
170 BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
171 {
172 BOOST_FOREACH(fs::path const& p, g.second)
173 {
174 paths.insert(get_path(p, f));
175 }
176 }
177
178 BOOST_FOREACH(std::string const& p, paths)
179 {
180 out << p << std::endl;
181 }
182 }
183 }
184}