monotone

monotone Mtn Source Tree

Root/manifest.cc

1// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
2// all rights reserved.
3// licensed to the public under the terms of the GNU GPL (>= 2)
4// see the file COPYING for details
5
6#include <string>
7#include <iterator>
8#include <sstream>
9#include <iostream>
10#include <algorithm>
11#include <iterator>
12
13#include <boost/regex.hpp>
14
15#include "app_state.hh"
16#include "file_io.hh"
17#include "manifest.hh"
18#include "transforms.hh"
19#include "sanity.hh"
20
21// this file defines the class of manifest_map objects, and various comparison
22// and i/o functions on them. a manifest specifies exactly which versions
23// of each file reside at which path location in a given tree.
24
25using namespace boost;
26using namespace std;
27
28string const manifest_file_name("manifest");
29
30// building manifest_maps
31
32class manifest_map_builder : public tree_walker
33{
34 app_state & app;
35 manifest_map & man;
36public:
37 manifest_map_builder(app_state & a, manifest_map & m);
38 virtual void visit_file(file_path const & path);
39};
40
41manifest_map_builder::manifest_map_builder(app_state & a, manifest_map & m)
42 : app(a), man(m)
43{
44}
45
46void manifest_map_builder::visit_file(file_path const & path)
47{
48
49 if (book_keeping_file(path()))
50 return;
51 if (app.lua.hook_ignore_file(path))
52 return;
53 hexenc<id> ident;
54 L(F("scanning file %s\n") % path);
55 calculate_ident(path, ident, app.lua);
56 man.insert(entry(path, file_id(ident)));
57}
58
59void build_manifest_map(file_path const & path,
60app_state & app,
61manifest_map & man)
62{
63 man.clear();
64 manifest_map_builder build(app,man);
65 walk_tree(path, build);
66}
67
68void build_manifest_map(app_state & app,
69manifest_map & man)
70{
71 man.clear();
72 manifest_map_builder build(app,man);
73 walk_tree(build);
74}
75
76
77void build_manifest_map(path_set const & paths,
78manifest_map & man,
79app_state & app)
80{
81 man.clear();
82 for (path_set::const_iterator i = paths.begin();
83 i != paths.end(); ++i)
84 {
85 hexenc<id> ident;
86 calculate_ident(*i, ident, app.lua);
87 man.insert(entry(*i, file_id(ident)));
88 }
89}
90
91void append_manifest_map(manifest_map const & m1,
92 manifest_map & m2)
93{
94 copy(m1.begin(), m1.end(), inserter(m2, m2.begin()));
95}
96
97
98// reading manifest_maps
99
100struct add_to_manifest_map
101{
102 manifest_map & man;
103 explicit add_to_manifest_map(manifest_map & m) : man(m) {}
104 bool operator()(match_results<std::string::const_iterator, regex::alloc_type> const & res)
105 {
106 std::string ident(res[1].first, res[1].second);
107 std::string path(res[2].first, res[2].second);
108 if (!book_keeping_file(path))
109 man.insert(entry(path, hexenc<id>(ident)));
110 else
111 throw oops("unsafe filename: " + path);
112 return true;
113 }
114};
115
116void read_manifest_map(data const & dat,
117 manifest_map & man)
118{
119 regex expr("^([[:xdigit:]]{40}) ([^[:space:]].+)$");
120 regex_grep(add_to_manifest_map(man), dat(), expr, match_not_dot_newline);
121}
122
123void read_manifest_map(manifest_data const & dat,
124 manifest_map & man)
125{
126 gzip<data> decoded;
127 data decompressed;
128 decode_base64(dat.inner(), decoded);
129 decode_gzip(decoded, decompressed);
130 read_manifest_map(decompressed, man);
131}
132
133
134
135// writing manifest_maps
136
137std::ostream & operator<<(std::ostream & out, entry const & e)
138{
139 path_id_pair pip(e);
140 return (out << pip.ident().inner()() << " " << pip.path()() << "\n");
141}
142
143
144void write_manifest_map(manifest_map const & man,
145manifest_data & dat)
146{
147 ostringstream sstr;
148 copy(man.begin(),
149 man.end(),
150 ostream_iterator<entry>(sstr));
151
152 data raw;
153 gzip<data> compressed;
154 base64< gzip<data> > encoded;
155
156 raw = sstr.str();
157 encode_gzip(raw, compressed);
158 encode_base64(compressed, encoded);
159 dat = manifest_data(encoded);
160}
161
162void write_manifest_map(manifest_map const & man,
163data & dat)
164{
165 ostringstream sstr;
166 for (manifest_map::const_iterator i = man.begin();
167 i != man.end(); ++i)
168 sstr << *i;
169 dat = sstr.str();
170}
171
172
173// manifest_maps are set-theoretic enough objects that we can use our
174// friendly <algorithm> routines
175
176void calculate_manifest_changes(manifest_map const & a,
177manifest_map const & b,
178manifest_changes & chg)
179{
180 chg.adds.clear();
181 chg.dels.clear();
182 set_difference(a.begin(), a.end(), b.begin(), b.end(),
183 inserter(chg.dels, chg.dels.begin()));
184 set_difference(b.begin(), b.end(), a.begin(), a.end(),
185 inserter(chg.adds, chg.adds.begin()));
186}
187
188
189void apply_manifest_changes(manifest_map const & a,
190 manifest_changes const & chg,
191 manifest_map & b)
192{
193 set<entry> tmp, deleted;
194 copy(a.begin(), a.end(), inserter(tmp, tmp.begin()));
195 set_difference(tmp.begin(), tmp.end(),
196 chg.dels.begin(), chg.dels.end(),
197 inserter(deleted, deleted.begin()));
198 b.clear();
199 set_union(deleted.begin(), deleted.end(),
200 chg.adds.begin(), chg.adds.end(),
201 inserter(b, b.begin()));
202}
203
204void write_manifest_changes(manifest_changes const & changes,
205 data & dat)
206{
207 ostringstream out;
208 for (set<entry>::const_iterator i = changes.dels.begin();
209 i != changes.dels.end(); ++i)
210 out << "- " << *i;
211 for (set<entry>::const_iterator i = changes.adds.begin();
212 i != changes.adds.end(); ++i)
213 out << "+ " << *i;
214 dat = out.str();
215}

Archive Download this file

Branches

Tags

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