monotone

monotone Mtn Source Tree

Root/src/rev_output.cc

1// Copyright (C) 2010 Derek Scherger <derek@echologic.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include "base.hh"
11#include <map>
12#include <set>
13#include <sstream>
14#include <vector>
15
16#include "cert.hh"
17#include "cset.hh"
18#include "dates.hh"
19#include "project.hh"
20#include "rev_output.hh"
21#include "revision.hh"
22
23using std::map;
24using std::ostringstream;
25using std::pair;
26using std::set;
27using std::string;
28using std::vector;
29
30void
31revision_header(revision_id const rid, revision_t const & rev,
32 string const & author, date_t const date,
33 branch_name const & branch, utf8 const & changelog,
34 string const & date_fmt, utf8 & header)
35{
36 vector<cert> certs;
37 key_id empty_key;
38 certs.push_back(cert(rid, author_cert_name,
39 cert_value(author, origin::user), empty_key));
40 certs.push_back(cert(rid, date_cert_name,
41 cert_value(date.as_iso_8601_extended(), origin::user),
42 empty_key));
43 certs.push_back(cert(rid, branch_cert_name,
44 cert_value(branch(), origin::user), empty_key));
45
46 if (!changelog().empty())
47 certs.push_back(cert(rid, changelog_cert_name,
48 cert_value(changelog(), origin::user), empty_key));
49
50 revision_header(rid, rev, certs, date_fmt, header);
51}
52
53void
54revision_header(revision_id const rid, revision_t const & rev,
55 vector<cert> const & certs, string const & date_fmt,
56 utf8 & header)
57{
58 ostringstream out;
59
60 out << string(70, '-') << '\n'
61 << _("Revision: ") << rid << '\n';
62
63 for (edge_map::const_iterator i = rev.edges.begin(); i != rev.edges.end(); ++i)
64 {
65 revision_id parent = edge_old_revision(*i);
66 if (!null_id(parent))
67 out << _("Parent: ") << parent << '\n';
68 }
69
70 cert_name const author(author_cert_name);
71 cert_name const date(date_cert_name);
72 cert_name const branch(branch_cert_name);
73 cert_name const tag(tag_cert_name);
74 cert_name const changelog(changelog_cert_name);
75 cert_name const comment(comment_cert_name);
76
77 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
78 if (i->name == author)
79 out << _("Author: ") << i->value << '\n';
80
81 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
82 if (i->name == date)
83 {
84 if (date_fmt.empty())
85 out << _("Date: ") << i->value << '\n';
86 else
87 {
88 date_t date(i->value());
89 out << _("Date: ") << date.as_formatted_localtime(date_fmt) << '\n';
90 }
91 }
92
93 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
94 if (i->name == branch)
95 out << _("Branch: ") << i->value << '\n';
96
97 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
98 if (i->name == tag)
99 out << _("Tag: ") << i->value << '\n';
100
101 // Output "custom" certs if we have any, under a heading of "Other certs"
102 bool need_to_output_heading = true;
103 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
104 {
105 if (i->name != author && i->name != branch && i->name != changelog &&
106 i->name != comment && i->name != date && i->name != tag)
107 {
108 if (need_to_output_heading)
109 {
110 out << _("Other certs:") << '\n';
111 need_to_output_heading = false;
112 }
113
114 out << " " << i->name << ": " << i->value << '\n';
115 }
116 }
117
118 out << "\n";
119
120 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
121 if (i->name == changelog)
122 {
123 out << _("Changelog: ") << "\n\n" << i->value << '\n';
124 if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
125 out << '\n';
126 }
127
128 for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
129 if (i->name == comment)
130 {
131 out << _("Comments: ") << "\n\n" << i->value << '\n';
132 if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
133 out << '\n';
134 }
135
136 header = utf8(out.str(), origin::internal);
137}
138
139void
140revision_summary(revision_t const & rev, utf8 & summary)
141{
142 // We intentionally do not collapse the final \n into the format
143 // strings here, for consistency with newline conventions used by most
144 // other format strings.
145
146 ostringstream out;
147 revision_id rid;
148 calculate_ident(rev, rid);
149
150 for (edge_map::const_iterator i = rev.edges.begin(); i != rev.edges.end(); ++i)
151 {
152 revision_id parent = edge_old_revision(*i);
153 cset const & cs = edge_changes(*i);
154
155 // A colon at the end of this string looked nicer, but it made
156 // double-click copying from terminals annoying.
157 if (null_id(parent))
158 out << _("Changes") << "\n\n";
159 else
160 out << _("Changes against parent ") << parent << "\n\n";
161
162 // presumably a merge rev could have an empty edge if one side won
163 if (cs.empty())
164 out << _("no changes") << '\n';
165
166 for (set<file_path>::const_iterator i = cs.nodes_deleted.begin();
167 i != cs.nodes_deleted.end(); ++i)
168 out << (F(" dropped %s") %*i) << '\n';
169
170 for (map<file_path, file_path>::const_iterator
171 i = cs.nodes_renamed.begin();
172 i != cs.nodes_renamed.end(); ++i)
173 out << (F(" renamed %s\n"
174 " to %s") % i->first % i->second) << '\n';
175
176 for (set<file_path>::const_iterator i = cs.dirs_added.begin();
177 i != cs.dirs_added.end(); ++i)
178 out << (F(" added %s") % *i) << '\n';
179
180 for (map<file_path, file_id>::const_iterator i = cs.files_added.begin();
181 i != cs.files_added.end(); ++i)
182 out << (F(" added %s") % i->first) << '\n';
183
184 for (map<file_path, pair<file_id, file_id> >::const_iterator
185 i = cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i)
186 out << (F(" patched %s") % i->first) << '\n';
187
188 for (map<pair<file_path, attr_key>, attr_value >::const_iterator
189 i = cs.attrs_set.begin(); i != cs.attrs_set.end(); ++i)
190 out << (F(" attr on %s\n"
191 " set %s\n"
192 " to %s")
193 % i->first.first % i->first.second % i->second) << '\n';
194
195 // FIXME: naming here could not be more inconsistent
196 // the cset calls it attrs_cleared
197 // the command is attr drop
198 // here it is called unset
199 // the revision text uses attr clear
200
201 for (set<pair<file_path, attr_key> >::const_iterator
202 i = cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i)
203 out << (F(" attr on %s\n"
204 " unset %s") % i->first % i->second) << '\n';
205
206 out << '\n';
207 }
208 summary = utf8(out.str(), origin::internal);
209}
210
211// Local Variables:
212// mode: C++
213// fill-column: 76
214// c-file-style: "gnu"
215// indent-tabs-mode: nil
216// End:
217// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

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