1 #include "tag-parser.hh"
2 #include "utility/File.cc"
7 // todo: const correctness
12 typedef std::vector
<std::string
> DependencyVector
;
13 typedef DependencyVector::iterator iterator
;
15 PkgNode (std::string i_name
)
21 iterator
Begin () {return depend
.begin();}
22 iterator
End () {return depend
.end();}
24 void AddDependency (const std::string
& dep
) {depend
.push_back(std::string(dep
));}
26 const std::string
& Name () {return name
;}
28 int Priority () {return priority
;}
31 friend class PkgGraph
;
34 DependencyVector depend
;
35 int priority
; // -1 = not evaluated yet; -2 = in evaluation;
38 class PkgGraph
: public std::map
<std::string
, PkgNode
*>
40 public: // TODO: duplication checking !!
41 void AddPkg (PkgNode
* pkg
) { (*this)[pkg
-> Name()] = pkg
; }
43 typedef std::map
<std::string
, PkgNode
*>::iterator iterator
;
45 int GetPriority (const std::string
& pkgname
)
47 iterator pi
= find(pkgname
);
49 std::cerr
<< "Warning: could not find package '" << pkgname
<< "'" << std::endl
;
53 PkgNode
& node
= *(pi
-> second
);
54 if (node
.priority
== -2) {
55 std::cerr
<< "Warning: circular dependency detected involving package '"
56 << pkgname
<< "'" << std::endl
;
58 } else if (node
.priority
== -1) {
61 for (PkgNode::iterator i
= node
.Begin(); i
!= node
.End(); i
++)
62 new_priority
= std::max (new_priority
, GetPriority(*i
));
63 node
.priority
= new_priority
+ 1;
71 class CacheFile
: public TagParser
76 : copyright("COPY","",""),
78 timestamp("TIMESTAMP","",""),
79 config_id("CONFIG-ID","",""),
80 version("ROCKVER","",""),
84 buildtime("BUILDTIME","",""),
89 error0("0-ERROR","",""),
90 error1("1-ERROR","",""),
91 error2("2-ERROR","",""),
92 error3("3-ERROR","",""),
93 error4("4-ERROR","",""),
94 error5("5-ERROR","",""),
95 error6("6-ERROR","",""),
96 error7("7-ERROR","",""),
97 error8("8-ERROR","",""),
98 error9("9-ERROR","","")
100 tags
.push_back(©right
);
101 tags
.push_back(×tamp
);
102 tags
.push_back(&config_id
);
103 tags
.push_back(&version
);
104 tags
.push_back(&logs
);
105 tags
.push_back(&buildtime
);
106 tags
.push_back(&size
);
107 tags
.push_back(&dep
);
109 tags
.push_back(&error0
);
110 tags
.push_back(&error1
);
111 tags
.push_back(&error2
);
112 tags
.push_back(&error3
);
113 tags
.push_back(&error4
);
114 tags
.push_back(&error5
);
115 tags
.push_back(&error6
);
116 tags
.push_back(&error7
);
117 tags
.push_back(&error8
);
118 tags
.push_back(&error9
);
121 PkgNode
* DepsFromFile(const std::string
& pkgname
, const std::string
& file
)
125 std::cerr
<< "warning: there were errors in the cache file of package '"
126 << pkgname
<< "'" << std::endl
;
128 PkgNode
* ret
= new PkgNode (pkgname
);
130 // split dep tag value into single tokens and add into PkgNode's Dependency vector.
131 std::stringstream
stream(dep
.value
);
136 ret
-> AddDependency(s
);
155 // Todo: replace those
171 std::string
PkgName (const std::string
& file
)
173 return Utility::File(file
).BasenameWOExtension();
179 bool operator() (PkgNode
* a
, PkgNode
* b
)
181 return a
->Priority() < b
->Priority();
188 DownArrow (unsigned int pkg_priority
)
190 start
= pkg_priority
;
194 void SetNeed (unsigned int by_priority
)
196 end
= std::max(end
, by_priority
);
199 // returns true iff a and this arrow can be drawn in the same column
200 bool Compatible (const DownArrow
& a
)
202 return (a
.start
> end
|| a
.end
< start
);
210 std::map
<std::string
, DownArrow
*> down_arrows
;
211 typedef std::map
<std::string
, DownArrow
*>::iterator arrow_iterator
;
213 void InsertAt(std::string
& s
, unsigned int char_pos
, char c
)
215 while (s
.length() <= char_pos
)
220 std::string
Template (unsigned int v_pos
)
222 arrow_iterator arr_end
= down_arrows
.end ();
223 std::string ret
= "";
225 for (arrow_iterator i
= down_arrows
.begin(); i
!= arr_end
; i
++) {
226 if (i
-> second
-> start
<= v_pos
&& i
-> second
-> end
> v_pos
)
227 InsertAt(ret
, 2*(i
-> second
-> h_pos
), '|');
233 std::string
HRef (PkgNode
& node
, unsigned int v_pos
)
235 std::string tmpl
= Template(v_pos
);
236 arrow_iterator arr_end
= down_arrows
.end ();
238 unsigned int h_min
= ((unsigned int) ((int) -1));
240 // comparism (1) is a workaround for those cross references
242 for (PkgNode::iterator dep_on
= node
.Begin(); dep_on
!= node
.End(); dep_on
++) {
243 arrow_iterator arrow
= down_arrows
.find(*dep_on
);
244 if (arrow
!= arr_end
&& arrow
-> second
-> start
< v_pos
/* (1) */) {
245 h_min
= std::min (h_min
, arrow
-> second
-> h_pos
);
246 InsertAt(tmpl
, 2*(arrow
-> second
-> h_pos
), '+');
250 arrow_iterator arrow
= down_arrows
.find(node
.Name());
251 if (arrow
!= arr_end
) {
252 h_min
= std::min (h_min
, arrow
-> second
-> h_pos
);
253 InsertAt(tmpl
, 2*(arrow
-> second
-> h_pos
), 'v');
256 for (unsigned int i
= 2*h_min
; i
< tmpl
.length(); i
++)
257 if (tmpl
[i
] != 'v' && tmpl
[i
] != '+')
266 std::vector
<PkgNode
*> needed
;
268 for (PkgGraph::iterator i
= pkg_graph
.begin(); i
!= pkg_graph
.end(); i
++) {
269 if (i
-> second
-> Priority () >= 0)
270 needed
.push_back (i
-> second
);
273 // sort after priority
274 std::sort (needed
.begin(), needed
.end(), PriorityCmp ());
276 arrow_iterator arr_end
= down_arrows
.end ();
280 // compute DownArrow lengh
281 for (unsigned int i
= 0; i
< needed
.size(); i
++) {
282 PkgNode
& current
= *(needed
[i
]);
283 down_arrows
[current
.Name()] = new DownArrow (i
);
284 for (PkgNode::iterator dep_on
= current
.Begin(); dep_on
!= current
.End(); dep_on
++) {
285 arrow_iterator arrow
= down_arrows
.find(*dep_on
);
286 if (arrow
!= arr_end
)
287 arrow
-> second
-> SetNeed(i
);
291 // greedyly arrange DownArrows horizontaly
292 for (unsigned int i
= 0; i
< needed
.size(); i
++) {
293 arrow_iterator cur_assign
= down_arrows
.find(needed
[i
] -> Name());
295 unsigned int h_pos
= 0;
301 for (unsigned int j
= 0; j
< i
; j
++) {
302 arrow_iterator assigned
= down_arrows
.find(needed
[j
] -> Name());
303 if (assigned
-> second
-> h_pos
== h_pos
)
304 if (!(assigned
-> second
-> Compatible(*(cur_assign
-> second
))))
309 cur_assign
-> second
-> h_pos
= h_pos
;
312 } while (!pos_found
);
317 for (unsigned int i
= 0; i
< needed
.size(); i
++) {
318 std::cout
<< HRef (*(needed
[i
]),i
) << "---" << needed
[i
] -> Name() << std::endl
319 << Template(i
) << std::endl
;
325 int main (int argc
, char** argv
)
328 std::cerr
<< argv
[0] << " <pkgs> <cachefile>+" << std::endl
;
332 std::string
package(argv
[1]);
336 cache_file
.DepsFromFile(
337 PkgName(*argv
), std::string(*argv
)));
341 pkg_graph
.GetPriority (package
);