monotone

monotone Mtn Source Tree

Root/paths.hh

1#ifndef __PATHS_H__
2#define __PATHS_H__
3
4// copyright (C) 2005 nathaniel smith <njs@pobox.com>
5// all rights reserved.
6// licensed to the public under the terms of the GNU GPL (>= 2)
7// see the file COPYING for details
8
9// safe, portable, fast, simple path handling -- in that order.
10// but they all count.
11//
12// this file defines the vocabulary we speak in when dealing with the
13// filesystem. this is an extremely complex problem by the time one worries
14// about normalization, security issues, character sets, and so on;
15// furthermore, path manipulation has historically been a performance
16// bottleneck in monotone. so the goal here is the efficient implementation
17// of a design that makes it hard or impossible to introduce as many classes
18// of bugs as possible.
19//
20// Our approach is to have three different types of paths:
21// -- system_path
22// this is a path to anywhere in the fs. it is in native format. it is
23// always absolute. when constructed from a string, it interprets the
24// string as being relative to the directory that monotone was run in.
25// (note that this may be different from monotone's current directory, as
26// when run in working copy monotone chdir's to the project root.)
27//
28// one can also construct a system_path from one of the below two types
29// of paths. this is intelligent, in that it knows that these sorts of
30// paths are considered to be relative to the project root. thus
31// system_path(file_path_internal("foo"))
32// is not, in general, the same as
33// system_path("foo")
34//
35// -- file_path
36// this is a path representing a versioned file. it is always
37// a fully normalized relative path, that does not escape the project
38// root. it is always relative to the project root.
39// you cannot construct a file_path directly from a string; you must pick
40// a constructor:
41// file_path_internal: use this for strings that come from
42// "monotone-internal" places, e.g. parsing revisions. this turns on
43// stricter checking -- the string must already be normalized -- and
44// is extremely fast. such strings are interpreted as being relative
45// to the project root.
46// file_path_external: use this for strings that come from the user.
47// these strings are normalized before being checked, and if there is
48// a problem trigger N() invariants rather than I() invariants. if in
49// a working directory, such strings are interpreted as being
50// _relative to the user's original directory_.
51// if not in a working copy, strings are treated as referring to some
52// database object directly.
53// file_path's also provide optimized splitting and joining
54// functionality.
55//
56// -- bookkeeping_path
57// this is a path representing something in the MT/ directory of a
58// working copy. it has the same format restrictions as a file_path,
59// except instead of being forbidden to point into the MT directory, it
60// is _required_ to point into the MT directory. the one constructor is
61// strict, and analogous to file_path_internal. however, the normal way
62// to construct bookkeeping_path's is to use the global constant
63// 'bookkeeping_root', which points to the MT directory. Thus to
64// construct a path pointing to MT/options, use:
65// bookkeeping_root / "options"
66//
67// All path types should always be constructed from utf8-encoded strings.
68//
69// All path types provide an "operator /" which allows one to construct new
70// paths pointing to things underneath a given path. E.g.,
71// file_path_internal("foo") / "bar" == file_path_internal("foo/bar")
72//
73// All path types subclass 'any_path', which provides:
74// -- emptyness checking with .empty()
75// -- a method .as_internal(), which returns the utf8-encoded string
76// representing this path for internal use. for instance, this is the
77// string that should be embedded into the text of revisions.
78// -- a method .as_external(), which returns a std::string suitable for
79// passing to filesystem interface functions. in practice, this means
80// that it is recoded into an appropriate character set, etc.
81// -- a operator<< for ostreams. this should always be used when writing
82// out paths for display to the user. at the moment it just calls one
83// of the above functions, but this is _not_ correct. there are
84// actually 3 different logical character sets -- internal (utf8),
85// user (locale-specific), and filesystem (locale-specific, except
86// when it's not, i.e., on OS X). so we need three distinct operations,
87// and you should use the correct one.
88//
89// all this means that when you want to print out a path, you usually
90// want to just say:
91// F("my path is %s") % my_path
92// i.e., nothing fancy necessary, for purposes of F() just treat it like
93// it were a string
94//
95//
96// There is also one "not really a path" type, 'split_path'. This is a vector
97// of path_component's, and semantically equivalent to a file_path --
98// file_path's can be split into split_path's, and split_path's can be joined
99// into file_path's.
100
101
102#include <iosfwd>
103#include <string>
104#include <vector>
105
106#include "numeric_vocab.hh"
107#include "vocab.hh"
108
109typedef u32 path_component;
110
111typedef std::vector<path_component> split_path;
112
113const path_component the_null_component = 0;
114
115inline bool
116null_name(path_component pc)
117{
118 return pc == the_null_component;
119}
120
121// It's possible this will become a proper virtual interface in the future,
122// but since the implementation is exactly the same in all cases, there isn't
123// much point ATM...
124class any_path
125{
126public:
127 // converts to native charset and path syntax
128 // this is a path that you can pass to the operating system
129 std::string as_external() const;
130 // leaves as utf8
131 std::string const & as_internal() const
132 { return data(); }
133 bool empty() const
134 { return data().empty(); }
135protected:
136 utf8 data;
137 any_path() {}
138 any_path(any_path const & other)
139 : data(other.data) {}
140 any_path & operator=(any_path const & other)
141 { data = other.data; return *this; }
142};
143
144std::ostream & operator<<(std::ostream & o, any_path const & a);
145
146class file_path : public any_path
147{
148public:
149 file_path() {}
150 // join a file_path out of pieces
151 file_path(split_path const & sp);
152
153 // this currently doesn't do any normalization or anything.
154 file_path operator /(std::string const & to_append) const;
155
156 void split(split_path & sp) const;
157
158 bool operator ==(const file_path & other) const
159 { return data == other.data; }
160
161 bool operator <(const file_path & other) const
162 { return data < other.data; }
163
164private:
165 typedef enum { internal, external } source_type;
166 // input is always in utf8, because everything in our world is always in
167 // utf8 (except interface code itself).
168 // external paths:
169 // -- are converted to internal syntax (/ rather than \, etc.)
170 // -- normalized
171 // -- assumed to be relative to the user's cwd, and munged
172 // to become relative to root of the working copy instead
173 // both types of paths:
174 // -- are confirmed to be normalized and relative
175 // -- not to be in MT/
176 file_path(source_type type, std::string const & path);
177 friend file_path file_path_internal(std::string const & path);
178 friend file_path file_path_external(utf8 const & path);
179};
180
181// these are the public file_path constructors
182inline file_path file_path_internal(std::string const & path)
183{
184 return file_path(file_path::internal, path);
185}
186inline file_path file_path_external(utf8 const & path)
187{
188 return file_path(file_path::external, path());
189}
190
191class bookkeeping_path : public any_path
192{
193public:
194 bookkeeping_path() {};
195 // path _should_ contain the leading MT/
196 // and _should_ look like an internal path
197 // usually you should just use the / operator as a constructor!
198 bookkeeping_path(std::string const & path);
199 bookkeeping_path operator /(std::string const & to_append) const;
200 // exposed for the use of walk_tree
201 static bool is_bookkeeping_path(std::string const & path);
202};
203
204extern bookkeeping_path const bookkeeping_root;
205
206// this will always be an absolute path
207class system_path : public any_path
208{
209public:
210 system_path() {};
211 system_path(system_path const & other) : any_path(other) {};
212 // the optional argument takes some explanation. this constructor takes a
213 // path relative to the working copy root. the question is how to interpret
214 // that path -- since it's possible to have multiple working copies over the
215 // course of a the program's execution (e.g., if someone runs 'checkout'
216 // while already in a working copy). if 'true' is passed (the default),
217 // then monotone will trigger an invariant if the working copy changes after
218 // we have already interpreted the path relative to some other working
219 // copy. if 'false' is passed, then the path is taken to be relative to
220 // whatever the current working copy is, and will continue to reference it
221 // even if the working copy later changes.
222 explicit system_path(any_path const & other,
223 bool in_true_working_copy = true);
224 // this path can contain anything, and it will be absolutified and
225 // tilde-expanded. it will considered to be relative to the directory
226 // monotone started in. it should be in utf8.
227 system_path(std::string const & path);
228 system_path(utf8 const & path);
229 system_path operator /(std::string const & to_append) const;
230};
231
232
233void
234save_initial_path();
235
236// returns true if working copy found, in which case cwd has been changed
237// returns false if working copy not found
238bool
239find_and_go_to_working_copy(system_path const & search_root);
240
241// this is like change_current_working_dir, but also initializes the various
242// root paths that are needed to interpret paths
243void
244go_to_working_copy(system_path const & new_working_copy);
245
246#endif

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status