tree checksum vpatch file split hunks

all signers: diana_coman

antecedents:

press order:

v_mod6_genesisdiana_coman

patch:

-
+ 5FC781391183934125154CE25C932B651B9B49F1A6BED879E124F6F9A2AD7C16543B0763731147634A224832206E94D1FCD3119C074B4D4FC225C4252257032D
v/v.pl
(0 . 0)(1 . 969)
5 #!/usr/bin/perl
6
7 # (C) 2014 - 2017 The Bitcoin Foundation. You do not have, nor can you ever
8 # acquire the right to use, copy or distribute this software ; Should you use
9 # this software for any purpose, or copy and distribute it to anyone or in any
10 # manner, you are breaking the laws of whatever soi-disant jurisdiction, and
11 # you promise to continue doing so for the indefinite future. In any case,
12 # please always : read and understand any software ; verify any PGP signatures
13 # that you use - for any purpose.
14
15 use strict;
16
17 my $version = "99994 K ";
18
19 my $tdir = get_homedir() . "/.gnupgtmp";
20
21 my $graph;
22 my %wot = ();
23 my %map = ();
24 my %tmp_map = ();
25 my %banners = ();
26 my %desc_map = ();
27 my %vp_map = ();
28
29 my ($pdir, $sdir, $wdir) = "";
30 my (@pfiles, @sfiles, @wfiles) = ();
31
32 sub get_homedir {
33 my $home = `echo \$HOME`; chomp($home);
34 return $home;
35 }
36
37 sub get_pwd {
38 my $pwd = `pwd`; chomp($pwd);
39 return $pwd;
40 }
41
42 sub set_files {
43 my ($dir) = @_;
44 if(!-d $dir) {
45 my $msg = "$dir directory does not exist.\n" .
46 "See 'init' or 'sync' commands in 'help'.\n";
47 death($msg);
48 }
49 my @a = `ls $dir | sort`;
50 return wash(@a);
51 }
52
53 sub wash { my (@a)=@_; my @b; foreach(@a) {chomp($_); push @b, $_;} return @b; }
54
55 sub init {
56 my ($URL, $pd, $sd) = @_;
57
58 if($URL && $pd && $sd) {
59 if(!-d $pd) { `mkdir -p $pd`; sync_all_vpatches($URL, $pd); }
60 else { print "$pd dir exists! Skipping initial Vpatch sync\n"; }
61 if(!-d $sd) { `mkdir -p $sd`; sync_seals($URL, $sd); }
62 else { print "$sd dir exists! Skipping initial Seal sync\n"; }
63 }
64 }
65
66 sub build_wot {
67 my $uid, my $banner, my $keyid, my $fp;
68 foreach my $pubkey (@wfiles) {
69 my $import = "gpg --homedir $tdir --logger-fd 1 --keyid-format=long " .
70 "--import $wdir/$pubkey 2> /dev/null";
71 my $res = `$import`;
72 $uid = $1 if $pubkey =~ /(.*)\.asc/; chomp($uid);
73 $banner = $1 if $res =~ /\"(.*)\"/; chomp($banner);
74 $keyid = $1 if $res =~ /key (.*)\:/; chomp($keyid);
75 my $res_fp = `gpg --homedir $tdir --logger-fd 1 --fingerprint $keyid`;
76 $fp = $1 if $res_fp =~ /Key fingerprint = (.*)/; $fp =~ s/\s+//g;
77 $wot{$uid} = { fp => $fp, banner => $banner };
78 }
79 }
80
81 sub validate_seals {
82 my $seal_key, my $seal_signatory, my $uid, my $fp, my $patch, my %sig;
83 foreach my $patch (@pfiles) {
84 foreach my $seal (@sfiles) {
85 $seal_key = $1 if $seal =~ /^(.*)\..*\..*$/;
86 $seal_signatory = $1 if $seal =~ /^.*\.(.*)\..*$/;
87 if($patch =~ /^$seal_key$/) {
88 if(exists $wot{$seal_signatory}) {
89 if(not exists $banners{$patch} && $patch ne "") {
90 $banners{$patch} = $patch;
91 %sig = ();
92 }
93 my $verify = "gpg --homedir $tdir --logger-fd 1 --verify $sdir/$seal " .
94 "$pdir/$patch";
95 my @res = `$verify`;
96 foreach my $r (@res) {
97 $fp = $1 if $r =~ /Primary key fingerprint: (.*)/; $fp =~ s/\s+//g;
98 foreach my $uidkey (sort keys %wot) {
99 if($wot{$uidkey}{fp} eq $fp) {
100 $uid = $uidkey;
101 last;
102 }
103 }
104 }
105 my $verified = "";
106 foreach my $r (@res) {
107 if($r =~ /Good signature/ && $uid ne "") {
108 $sig{$wot{$uid}{fp}} = $uid;
109 $banners{$patch} = {%sig};
110 $verified = "true";
111 last;
112 }
113 }
114 if($verified ne "true") {
115 my $border = "-----------------------------------------" .
116 "-----------------------------------------";
117 print "$border\n";
118 print "WARNING: $seal is an INVALID seal for $patch!\n";
119 my $msg = "Check that this user is in your WoT.\n" .
120 "Otherwise remove the invalid seal from your SEALS directory.";
121 print "$msg\n";
122 print "$border\n";
123 death();
124 }
125 $verified = "";
126 }
127 }
128 }
129 }
130 }
131
132 sub build_map {
133 my %vpdata;
134 @pfiles = ();
135 foreach my $vpatch (keys %banners) {
136 push @pfiles, $vpatch;
137 }
138 foreach my $pfile (@pfiles) {
139 $map{$pfile} = $pfile;
140 my @patch = `cat $pdir/$pfile`;
141 my $src_file = "", my $ante_hash = "", my $desc_hash = "";
142 foreach my $p (@patch) {
143 $src_file = $1, $ante_hash = $2 if $p =~ /^--- (.*) (.*)/;
144 $desc_hash = $1 if $p =~ /^\+\+\+ .* (.*)/;
145 if($src_file && $ante_hash && $desc_hash) {
146 death("$pfile is an invalid vpatch!\n") if $ante_hash eq $desc_hash;
147 $vpdata{$src_file} = { a => $ante_hash, b => $desc_hash };
148 $map{$pfile} = {%vpdata};
149 $src_file = "", $ante_hash = "", $desc_hash = "";
150 }
151 }
152 death("Error! $pfile is an invalid vpatch file.\n") if !%vpdata;
153 %vpdata = ();
154 }
155 return %map;
156 }
157
158 sub roots {
159 my @roots = ();
160 my $is_root = "false";
161 foreach my $vpatch (keys %map) {
162 my %ante = antecedents($vpatch);
163 if(!%ante) {
164 foreach my $src_file_name (keys %{$map{$vpatch}}) {
165 if($map{$vpatch}{$src_file_name}->{a} eq "false") {
166 $is_root = "true";
167 next;
168 } else {
169 $is_root = "false";
170 last;
171 }
172 }
173 push @roots, $vpatch if $is_root eq "true";
174 }
175 }
176 return @roots;
177 }
178
179 sub leafs {
180 my @leafs;
181 foreach my $vpatch (keys %map) {
182 my %desc = descendants($vpatch);
183 push @leafs, $vpatch if !%desc;
184 }
185 return @leafs;
186 }
187
188 sub traverse_desc {
189 my (%st) = @_;
190 my %desc;
191 foreach my $k (keys %map) {
192 my @tmp = ();
193 foreach my $src_file_name (keys %{$map{$k}}) {
194 my $src_file = $map{$k}{$src_file_name};
195 foreach my $sf_name (keys %st) {
196 my $sf = $st{$sf_name};
197 if($src_file_name eq $sf_name &&
198 $src_file->{a} eq $sf->{b} &&
199 $src_file->{a} ne "false") {
200 push @tmp, $sf_name;
201 $desc{$k} = [@tmp];
202 }
203 }
204 }
205 }
206 return %desc;
207 }
208
209 sub traverse_ante {
210 my (%st) = @_;
211 my %ante;
212 foreach my $k (keys %map) {
213 my @tmp = ();
214 foreach my $src_file_name (keys %{$map{$k}}) {
215 my $src_file = $map{$k}{$src_file_name};
216 foreach my $sf_name (keys %st) {
217 my $sf = $st{$sf_name};
218 if($src_file_name eq $sf_name &&
219 $src_file->{b} eq $sf->{a} &&
220 $src_file->{b} ne "false") {
221 push @tmp, $sf_name;
222 $ante{$k} = [@tmp];
223 }
224 }
225 }
226 }
227 return %ante;
228 }
229
230 sub search_map {
231 my ($search_key) = @_;
232 if(exists $map{$search_key}) {
233 return %{$map{$search_key}};
234 } else {
235 death("Error! Could not find vpatch \"$search_key\" in $pdir\n");
236 }
237 }
238
239 sub antecedents {
240 my ($vpatch) = @_;
241 return traverse_ante(search_map($vpatch));
242 }
243
244 sub descendants {
245 my ($vpatch) = @_;
246 return traverse_desc(search_map($vpatch));
247 }
248
249 sub get_signatories {
250 my ($vpatch) = @_;
251 my @sigs;
252 foreach my $k (keys %banners) {
253 foreach my $fp (keys %{$banners{$k}}) {
254 my $uid = $banners{$k}{$fp};
255 push @sigs, $uid if $vpatch eq $k;
256 }
257 }
258 push @sigs, "WILD" if !@sigs;
259 return "(" . join(', ', sort @sigs) . ")";
260 }
261
262 sub build_flow {
263 my @flow = ();
264 my @roots = roots();
265 %tmp_map = %map;
266 foreach my $root (@roots) {
267 my %desc = descendants($root);
268 if(%desc) {
269 $desc_map{$root} = [keys %desc];
270 get_all_descendant_nodes(sort keys %desc);
271 verify_ante($root);
272 } else {
273 $desc_map{$root} = [];
274 }
275 }
276 @flow = toposort(%desc_map);
277 %map = scrub_map(@flow);
278 return @flow;
279 }
280
281 sub scrub_map {
282 my (@flow) = @_;
283 foreach my $k (keys %tmp_map) {
284 if(!grep {/$k/} @flow) { delete $tmp_map{$k} if exists $tmp_map{$k}; }
285 }
286 return %tmp_map;
287 }
288
289 sub verify_ante {
290 my (@vpatch) = @_;
291 my %desc = ();
292 foreach my $vp (@vpatch) {
293 %desc = descendants($vp);
294 if(%desc) {
295 foreach my $a (sort keys %desc) {
296 check_ante($a);
297 }
298 }
299 }
300 if(%desc) {
301 verify_ante(sort keys %desc);
302 }
303 }
304
305 sub check_ante {
306 my ($vp) = @_;
307 my @curr_node_edge_hashes = ();
308 my @verified_hashes = ();
309 my %ante = antecedents($vp);
310 foreach my $curr_node_edge (keys %{$tmp_map{$vp}}) {
311 if($tmp_map{$vp}{$curr_node_edge}->{a} ne "false") {
312 push @curr_node_edge_hashes, $tmp_map{$vp}{$curr_node_edge}->{a};
313 }
314 foreach my $ante_node (keys %ante) {
315 foreach my $ante_node_edge (keys %{$tmp_map{$ante_node}}) {
316 next if $curr_node_edge ne $ante_node_edge;
317 if($tmp_map{$vp}{$curr_node_edge}->{a} eq
318 $tmp_map{$ante_node}{$ante_node_edge}->{b}) {
319 push @verified_hashes, $tmp_map{$vp}{$curr_node_edge}->{a};
320 }
321 }
322 }
323 }
324 if(@curr_node_edge_hashes != @verified_hashes) {
325 remove_desc($vp);
326 }
327 }
328
329 sub remove_desc {
330 my (@vp) = @_;
331 my %desc = ();
332 foreach my $v (@vp) {
333 delete $desc_map{$v} if exists $desc_map{$v};
334 delete $tmp_map{$v} if exists $tmp_map{$v};
335 my %desc = descendants($v);
336 next if !%desc;
337 foreach my $d (keys %desc) {
338 foreach my $dkeys (keys %desc_map) {
339 my @tmp = @{$desc_map{$dkeys}};
340 if(@tmp) {
341 my $offset = 0;
342 foreach my $t (@tmp) {
343 if($t eq $d) {
344 splice @tmp, $offset, 1;
345 }
346 $offset++;
347 }
348 $desc_map{$dkeys} = [@tmp];
349 }
350 }
351 }
352 remove_desc(sort keys %desc) if %desc;
353 }
354 }
355
356 sub get_all_descendant_nodes {
357 my (@vpatch) = @_;
358 my %desc = ();
359 foreach my $vp (@vpatch) {
360 %desc = descendants($vp);
361 if(keys %desc) {
362 my @dkeys = keys %desc;
363 $desc_map{$vp} = [@dkeys];
364 get_all_descendant_nodes(sort @dkeys);
365 }
366 if(!%desc) {
367 $desc_map{$vp} = [];
368 }
369 }
370 return %desc_map;
371 }
372
373 sub toposort {
374 my (%unsorted) = @_;
375 my $acyclic = "", my $flag = "f", my @flow = ();
376 while(%unsorted) {
377 $acyclic = "false";
378 foreach my $node (sort keys %unsorted) {
379 my @edges = @{$unsorted{$node}};
380 foreach my $edge (@edges) {
381 $flag = "t" and last if exists $unsorted{$edge};
382 }
383 if($flag ne "t") {
384 $acyclic = "true";
385 delete $unsorted{$node};
386 push @flow, $node;
387 }
388 $flag = "";
389 }
390 if(!$acyclic eq "true") {
391 death("Cyclic Graph!\n");
392 }
393 }
394 return reverse @flow;
395 }
396
397 sub press_vpatches {
398 my ($p, @flow) = @_;
399 my @press = @{$p};
400 my $v = 1 and shift @press if $press[0] =~ /^v$|^verbose$/i;
401 death("HEAD: $press[1] not found in flow\n") if !grep /^$press[1]$/, @flow;
402 `rm -rf $press[0]` if -d $press[0];
403 `mkdir -p $press[0]`;
404 foreach my $vp (@flow) {
405 if($v) {
406 my @out = `patch -F 0 -E --dir $press[0] -p1 < $pdir/$vp 2>&1`;
407 print "$vp\n";
408 foreach my $o (@out) { print " $o"; }
409 } else {
410 `patch -F 0 -E --dir $press[0] -p1 < $pdir/$vp`;
411 }
412 %vp_map = ();
413 verify_pressed($press[0], add_pressed($vp));
414 last if $vp eq $press[1];
415 }
416 }
417
418 sub add_pressed {
419 my ($vpatch) = @_;
420 $vp_map{$vpatch} = $map{$vpatch};
421 return %vp_map;
422 }
423
424 sub get_filepath {
425 my ($fp) = @_;
426 $fp =~ /^[a|b]\/(.*)$/;
427 return $1;
428 }
429
430 sub verify_pressed {
431 my ($press_dir, %vp_map) = @_;
432 foreach my $vp (keys %vp_map) {
433 foreach my $src_file_name (keys %{$vp_map{$vp}}) {
434 my $file_hash = $vp_map{$vp}{$src_file_name}{b};
435 if($file_hash ne "false") {
436 my $fp = $press_dir . "/" . get_filepath($src_file_name);
437 my $hashed = `sha512sum $fp`;
438 $hashed =~ /^(.*) .*$/;
439 my $pressed_hash = $1;
440 if($file_hash ne $pressed_hash) {
441 print " File: $fp\n" .
442 "Expected: $file_hash\n" .
443 " Actual: $pressed_hash\n";
444 death("Pressed file hash did not match expected!\n");
445 }
446 }
447 }
448 }
449 }
450
451 sub sync_seals {
452 my ($URL, $out) = @_;
453 if(!-d $out) { `mkdir -p $out`; }
454 my $wget = "wget -q -r -nd -N --no-parent " .
455 "--reject \"index.html*\" $URL/v/seals/ -P $out";
456 `$wget`;
457 print "Seal sync complete to \"$out\"\n";
458 }
459
460 sub sync_vpatches {
461 my ($URL, $out, @sync) = @_;
462 my $wget = "";
463 if(!-d $out) { `mkdir -p $out`; }
464 foreach my $vpatch (@sync) {
465 $wget = "wget -q -r -nd -N --no-parent " .
466 "--reject \"index.html*\" $URL/v/patches/$vpatch -P $out";
467 `$wget`;
468 print "$vpatch sync complete to \"$out\"\n";
469 }
470 }
471
472 sub sync_all_vpatches {
473 my ($URL, $out) = @_;
474 if(!-d $out) { `mkdir -p $out`; }
475 my $wget = "wget -q -r -nd -N --no-parent " .
476 "--reject \"index.html*\" $URL/v/patches/ -P $out";
477 `$wget`;
478 print "Full vpatch sync complete to \"$out\"\n";
479 }
480
481 sub sync_everything {
482 my ($URL, $pd, $sd) = @_;
483 sync_all_vpatches($URL, $pd);
484 sync_seals($URL, $sd);
485 }
486
487 sub build_desc_full_graph {
488 $graph->set_attributes("graph",
489 {
490 font => "monospace",
491 label => "..::[ The Bitcoin Foundation: Vpatch Graph ]::.."
492 });
493 $graph->set_attributes("node",
494 {
495 linkbase => "http://thebitcoin.foundation/v/patches/",
496 autolink => "name",
497 color => "blue"
498 });
499 my @roots = roots();
500 foreach my $root (@roots) {
501 my $node = $graph->add_node($root);
502 $node->set_attribute("title", "Signed By: " . get_signatories($root));
503 my %desc = descendants($root);
504 my @dkeys = keys %desc;
505 add_desc_edges($root, @dkeys);
506 my @sn = $graph->source_nodes();
507 add_desc_src_files($sn[0]);
508 }
509 }
510
511 sub add_desc_edges {
512 my ($origin, @vpatch) = @_;
513 my %desc = ();
514 foreach my $vp (@vpatch) {
515 %desc = descendants($vp);
516 my $node = $graph->add_node($vp);
517 my $sigs = get_signatories($vp);
518 $node->set_attribute("title", "Signed By: $sigs");
519 $graph->add_edge_once($origin, $vp);
520 if(keys %desc) {
521 my @dkeys = sort keys %desc;
522 add_desc_edges($vp, @dkeys);
523 }
524 }
525 }
526
527 sub add_desc_src_files {
528 my ($node) = @_;
529 if($node != "") {
530 my %desc = descendants($node->name());
531 my @suc = $node->successors();
532 foreach my $s (@suc) {
533 my $name = $s->name();
534 my @edges = $node->edges_to($s);
535 foreach my $e (@edges) {
536 $e->set_attribute("title", "[ " .
537 join('; ', sort @{$desc{$name}}) . " ]");
538 add_desc_src_files($s);
539 }
540 }
541 }
542 }
543
544 sub rank_leafs_gviz {
545 build_desc_full_graph();
546 my $gviz = $graph->as_graphviz();
547 my @leafs = leafs();
548 $gviz =~ s/GRAPH_0/VPATCH_GRAPH/;
549 $gviz =~ s/rankdir=LR/rankdir=BT,ranksep=1.00,nodesep=.50/;
550 $gviz =~ s/}$//;
551 $gviz .= " { rank=same; ";
552 foreach my $l (@leafs) {
553 $gviz .= "\"$l\" ";
554 }
555 $gviz .= "}\n}";
556 return $gviz;
557 }
558
559 sub make_tmpdir {
560 my ($dir) = @_;
561 `mkdir -p $dir && chmod 0700 $dir` if !-d $dir or die "$dir exists! $!";
562 }
563
564 sub death {
565 my ($msg) = @_;
566 remove_tmpdir($tdir);
567 die "$msg";
568 }
569
570 sub remove_tmpdir {
571 my ($dir) = @_;
572 `rm -rf $dir` if -d $dir;
573 }
574
575 sub print_graph {
576 my ($graph, @gv) = @_;
577 if(!@gv) {
578 print "$graph\n";
579 } elsif($#gv eq 1) {
580 open FH, ">$gv[0]"; print FH "$graph\n";
581 close FH;
582 print "Printed Graphviz dot file to $gv[0]\n";
583 my @which = `which dot`; chomp($which[0]);
584 if($which[0] =~ /dot/) {
585 `$which[0] -Tsvg $gv[0] > $gv[1]`;
586 } else {
587 print "`dot` binary not found, check if 'graphviz' is installed\n";
588 }
589 print "Executed `dot` and built svg html output file: $gv[1]\n";
590 } else {
591 open FH, ">$gv[0]"; print FH "$graph\n";
592 close FH;
593 print "Printed Graphviz dot file to $gv[0]\n";
594 }
595 }
596
597 sub get_mirrors {
598 my ($out) = @_;
599 my @mirror_sigs = ();
600 if(!-d $out) { `mkdir -p $out`; }
601 my $wget = "wget -q -r -nd -N --no-parent " .
602 "--reject \"index.html*\" -A 'mirrors.*' " .
603 "http://thebitcoin.foundation/v/ -P $out";
604 `$wget`;
605
606 my @sigs = `ls $out | sort`;
607 @sigs = wash(@sigs);
608 foreach my $sig (@sigs) {
609 my $who = $1 if $sig =~ /.*\..*\.(.*)\..*/;
610 my $verify = "gpg --homedir $tdir --logger-fd 1 --verify $out/$sig " .
611 "$out/mirrors.txt";
612 my @res = `$verify`;
613 foreach my $r (@res) {
614 if($r =~ /Good signature/) {
615 push @mirror_sigs, $who;
616 next;
617 }
618 }
619 }
620 return @mirror_sigs;
621 }
622
623 sub print_mirrors {
624 my ($out) = @_;
625 my @mirror_sigs = get_mirrors($out);
626
627 if(-d $out) {
628 my @mirrors = `cat $out/mirrors.txt`;
629 print "Mirrors signed by (" . join(', ', sort @mirror_sigs) . "):\n";
630 foreach(@mirrors) { chomp($_); print "$_\n"; }
631 }
632 }
633
634 sub print_roots {
635 my @r = roots();
636 foreach(@r) {
637 print "Root: $_ " . get_signatories($_) . "\n";
638 }
639 }
640
641 sub print_leafs {
642 my @l = leafs();
643 foreach(@l) {
644 print "Leaf: $_ " . get_signatories($_) . "\n";
645 }
646 }
647
648 sub print_wot {
649 my ($finger) = @_;
650 if(%wot) {
651 foreach my $uid (sort keys %wot) {
652 if(!$finger) {
653 print "$uid:$wot{$uid}{fp}:$wot{$uid}{banner}\n";
654 } else {
655 print "$uid-" . substr($wot{$uid}{fp}, -16) .
656 ":$wot{$uid}{fp}:$wot{$uid}{banner}\n";
657 }
658 }
659 }
660 }
661
662 sub print_antecedents {
663 my ($vpatch) = @_;
664 my %ante = antecedents($vpatch);
665 my $sigs;
666 foreach my $a (sort keys %ante) {
667 $sigs = get_signatories($a);
668 print "Antecedent: $a $sigs [ " . join('; ', sort @{$ante{$a}}) . " ]\n";
669 }
670 }
671
672 sub print_descendants {
673 my ($vpatch) = @_;
674 my %desc = descendants($vpatch);
675 my $sigs;
676 foreach my $d (sort keys %desc) {
677 $sigs = get_signatories($d);
678 print "Descendant: $d $sigs [ " . join('; ', sort @{$desc{$d}}) . " ]\n";
679 }
680 }
681
682 sub print_origin {
683 my ($hash) = @_;
684 my $found = "f";
685 foreach my $k (keys %map) {
686 foreach my $sf (keys %{$map{$k}}) {
687 if($map{$k}{$sf}{b} eq $hash) {
688 $found = "t";
689 print "Origin: $k " . get_signatories($k) . "\n";
690 }
691 }
692 }
693 print "No Origin Found by Hash: $hash\n" if $found ne "t";
694 }
695
696 sub print_flow {
697 my (@flow) = @_;
698 foreach(@flow) { print "$_ " . get_signatories($_) . "\n"; }
699 }
700
701 sub get_version {
702 my $version_text = << "END_VERSION_TEXT";
703 ################################################################################
704 # ..::[ The Bitcoin Foundation: V ]::.. #
705 # #
706 # Version: $version #
707 # Author: mod6 #
708 # Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF #
709 # #
710 ################################################################################
711 END_VERSION_TEXT
712 return $version_text;
713 }
714
715 sub short_help {
716 my ($flag) = @_;
717 my $short_help = << "END_SHORT_HELP";
718 ################################################################################
719 # ..::[ The Bitcoin Foundation: V ]::.. #
720 # #
721 # Version: $version #
722 # Author: mod6 #
723 # Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF #
724 # #
725 # Usage: v.pl #
726 # (m | mirrors) (<output_dir>) #
727 # (i | init) (mirror_url) [(<pdir> <sdir>)] #
728 # (wd | wotdir) (<wotdir>) #
729 # (pd | patchdir) (<patchdir>) #
730 # (sd | sealdir) (<sealdir>) #
731 # (w | wot) [ finger ] #
732 # (r | roots) #
733 # (l | leafs) #
734 # (f | flow) #
735 # (p | press) (<press_dir> <head>) #
736 # (ss | sync-seals) (<mirror_url> <sdir>) #
737 # (sv | sync-vpatches) (<mirror_url> <pdir> <vpatches>... ) #
738 # (sa | sync-all-vpatches) (<mirror_url> <pdir>) #
739 # (se | sync-everything) (<mirror_url> <pdir> <sdir>) #
740 # (a | ante | antecedents) (<vpatch>) #
741 # (d | desc | descendants) (<vpatch>) #
742 # (o | origin) (<sha512_hash>) #
743 # (g | graph) (<output_dotfile> [<output_svg_html_file>]) #
744 # (v | version) #
745 # (h | ? | help) #
746 # #
747 END_SHORT_HELP
748 my $l = "########################################" .
749 "########################################\n";
750 if($flag) { $short_help .= $l; }
751 return $short_help;
752 }
753
754 sub long_help {
755 print short_help();
756 my $long_help = << "END_LONG_HELP";
757 # Commands: #
758 # m, mirrors (<output_dir>) #
759 # Will attempt to retrieve, cryptographically verify and print entries #
760 # in this list for usage in other commands. Mirrors command my only be #
761 # invoked by itself. [See: sync-seals, sync-vpatches, sync-everything] #
762 # #
763 # i, init (<mirror_url>) [(<pdir> <sdir>)] #
764 # init should be run as the first command executed with V. init only #
765 # requires one option: <mirror_url>. The <pdir> and <sdir> options are #
766 # optional. Use these if you want to override the default Vpatches and #
767 # Seals directories in that exact order. #
768 # #
769 # Defaults: "~/.wot", "patches" (in present working directory) and #
770 # "~/.seals" will be used as defaults. WoTs pubkeys can not be sync'd #
771 # these need to be placed in the WoT directory manually. #
772 # #
773 # Set <mirror_url> to one of the signed URLs in the PGP signed mirrors #
774 # list at: http://thebitcoin.foundation/v/mirrors.txt #
775 # #
776 # wd, wotdir (<wotdir>) #
777 # Given the required option <wotdir>, overrides the default wotdir #
778 # ( .wot in the current working directory ) containing PGP public keys. #
779 # #
780 # pd, patchdir (<patchdir>) #
781 # Given required option of <patchdir>, overrides the default #
782 # patchdir ( ./patches ) containing vpatch files. #
783 # #
784 # sd, sealdir (<sealdir>) #
785 # Given required option of <sealdir>, overrides the default sealdir #
786 # ( .seals in the current working directory ) containing PGP detached #
787 # signatures of vpatch files. #
788 # #
789 # w, wot [ finger ] #
790 # Loads PGP public keys from wotdir and prints the WoT to stdout #
791 # #
792 # r, roots #
793 # Finds the root vpatches (which have no antecedents) and prints them #
794 # to stdout. #
795 # #
796 # l, leafs #
797 # Finds the leaf vpatches (which have no descendants) and prints them #
798 # to stdout. #
799 # #
800 # f, flow #
801 # Prints the topological flow of vpatches based on precedence. #
802 # #
803 # p, press (<press_dir> <head>) #
804 # Given required options <press_dir> output directory and <vpatch> #
805 # press will apply vpatches in topologicial order up through the #
806 # supplied (head) vpatch. Will print patching output if 'verbose' flag #
807 # is supplied immediately after ( p | press ) option. #
808 # See: ( f | flow ) to view the topological ordering. #
809 # #
810 # ss, sync-seals (<mirror_url> <sdir>) #
811 # Given required options of <mirror_url> and output directory <sdir> #
812 # will pull all of the available seal files from the given mirror into #
813 # output directory. #
814 # #
815 # sv, sync-vpatches (<mirror_url> <pdir> <vpatch>... ) #
816 # Given required options of <mirror_url> and output directory <pdir> #
817 # will pull the requested vpatch(s) from the given mirror into output #
818 # directory. #
819 # #
820 # sa, sync-all-vpatches (<mirror_url> <pdir>) #
821 # Given required options of <mirror_url> and output directory <pdir> #
822 # will pull all available vpatches from the given mirror into output #
823 # directory. #
824 # #
825 # se, sync-everything (<mirror_url> <pdir> <sdir>) #
826 # Given required options of <mirror_url>, <pdir>, and <sdir>; #
827 # sync-everything will pull all of the available seals and vpatches #
828 # available at the given mirror. #
829 # #
830 # a, ante, antecedents (<vpatch>) #
831 # Finds the antecedents of a given vpatch and prints the results to #
832 # stdout #
833 # #
834 # d, desc, descendants (<vpatch>) #
835 # Finds the descendants of a given vpatch and prints the results to #
836 # stdout #
837 # #
838 # o, origin (<sha512_hash>) #
839 # Returns the vpatch and signatories where the given hash originated in #
840 # the source tree. #
841 # #
842 # g, graph (<output_dotfile> [<output_svg_html_file>]) #
843 # Builds a complete directed GraphViz graph of all vpatches from a #
844 # topological flow and prints the Dot language output to file. If the #
845 # output_svg_html_file argument is supplied the V will attempt to parse #
846 # the output_dotfile into an html file; Requires having separately #
847 # installed 'graphviz' ahead of time. #
848 # #
849 # v, version #
850 # Prints the version message. #
851 # #
852 # h, ?, help #
853 # Prints this full help message. #
854 # #
855 ################################################################################
856 END_LONG_HELP
857 return $long_help;
858 }
859
860 sub main {
861 my $cmd;
862 if(@ARGV > 0) { $cmd = shift @ARGV; }
863 else { print "Unknown or missing option!\n"; print short_help("t"); return; }
864
865 my $home = get_homedir();
866 my $pwd = get_pwd();
867 $wdir = "$pwd/.wot";
868 $pdir = "$pwd/patches";
869 $sdir = "$pwd/.seals";
870
871 if(($cmd =~ /^m$|^mirrors$/i ||
872 $cmd =~ /^i$|^init$/i ||
873 $cmd =~ /^wd$|^wotdir$/i ||
874 $cmd =~ /^pd$|^patchdir$/i ||
875 $cmd =~ /^sd$|^sealdir$/i ||
876 $cmd =~ /^p$|^press$/i ||
877 $cmd =~ /^ss$|^sync-seals$/i ||
878 $cmd =~ /^sv$|^sync-vpatches$/i ||
879 $cmd =~ /^sa$|^sync-all-vpatches$/i ||
880 $cmd =~ /^sa$|^sync-all-vpatches$/i ||
881 $cmd =~ /^se$|^sync-everything$/i ||
882 $cmd =~ /^a$|^ante$|^antecedents$/i ||
883 $cmd =~ /^d$|^desc$|^descendants$/i ||
884 $cmd =~ /^o$|^origin$/i ||
885 $cmd =~ /^g$|^graph$/i) && !@ARGV) {
886 print "Option \"$cmd\" requires arguments!\n";
887 print short_help("t"); return;
888 }
889
890 my @tmp = ();
891 while(@ARGV > 0) {
892 if($ARGV[0] =~ /^wd$|^wotdir$/) {
893 shift @ARGV; $wdir = shift @ARGV; next;
894 } elsif($ARGV[0] =~ /^pd$|^patchdir$/) {
895 shift @ARGV; $pdir = shift @ARGV; next;
896 } elsif($ARGV[0] =~ /^sd$|^sealdir$/) {
897 shift @ARGV; $sdir = shift @ARGV; next;
898 } else {
899 push @tmp, shift @ARGV;
900 }
901 }
902 @ARGV = @tmp;
903
904 @wfiles = set_files($wdir);
905 build_wot();
906
907 if($cmd =~ /^h$|^help$|^\?$/) { print long_help(); return; }
908 if($cmd =~ /^i$|^init$/) {
909 if(@ARGV == 1) {
910 init(@ARGV, $pdir, $sdir); return;
911 } elsif(@ARGV == 3) {
912 $sdir = pop @ARGV; $pdir = pop @ARGV;
913 init(@ARGV, $pdir, $sdir); return;
914 } else {
915 print "Incorrect number of arguments passed to init!\n";
916 print short_help("t"); return;
917 }
918 }
919
920 if($cmd =~ /^m$|^mirrors$/) { print_mirrors(@ARGV); return; }
921 if($cmd =~ /^w$|^wot$/) { print_wot(@ARGV); return; }
922 if($cmd =~ /^v$|^version$/) { print get_version(); return; }
923
924 @pfiles = set_files($pdir);
925 @sfiles = set_files($sdir);
926
927 validate_seals();
928 build_map();
929 my @flow = build_flow();
930
931 if ($cmd =~ /^r$|^roots$/) { print_roots(); }
932 elsif($cmd =~ /^l$|^leafs$/) { print_leafs(); }
933 elsif($cmd =~ /^f$|^flow$/) { print_flow(@flow); }
934 elsif($cmd =~ /^p$|^press$/) {
935 if(@ARGV < 2) {
936 print "$cmd requires two arguments: (<press_dir> <head>)\n\n";
937 print short_help("t"); }
938 else { press_vpatches(\@ARGV, @flow); } }
939 elsif($cmd =~ /^ss$|^sync-seals$/) {
940 if(@ARGV < 2) {
941 print "$cmd requires two arguments: (<mirror_url> <sdir>)\n\n";
942 print short_help("t"); }
943 else { sync_seals(@ARGV); } }
944 elsif($cmd =~ /^sv$|^sync-vpatches$/) {
945 if(@ARGV < 3) {
946 print "$cmd requires three arguments: " .
947 "(<mirror_url> <pdir> <vpatch>... )\n\n"; print short_help("t"); }
948 else { sync_vpatches(@ARGV); } }
949 elsif($cmd =~ /^sa$|^sync-all-vpatches$/) {
950 if(@ARGV < 2) {
951 print "$cmd requires two arguments: " .
952 "(<mirror_url> <pdir>)\n\n"; print short_help("t"); }
953 else { sync_all_vpatches(@ARGV); } }
954 elsif($cmd =~ /^se$|^sync-everything$/) {
955 if(@ARGV < 3) {
956 print "$cmd requires three arguments: " .
957 "(<mirror_url> <pdir> <sdir>)\n\n"; print short_help("t"); }
958 else { sync_everything(@ARGV); } }
959 elsif($cmd =~ /^a$|^ante$|^antecedents$/) { print_antecedents(@ARGV); }
960 elsif($cmd =~ /^d$|^desc$|^descendants$/) { print_descendants(@ARGV); }
961 elsif($cmd =~ /^o$|^origin$/) { print_origin(@ARGV); }
962 elsif($cmd =~ /^g$|^graph$/) {
963 my $mod = "Graph::Easy";
964 (my $req = $mod . ".pm") =~ s{::}{/}g;
965 require $req;
966 $graph = $mod->new();
967 print_graph(rank_leafs_gviz(), @ARGV); }
968 else { print "Unknown option: \"$cmd\"\n"; print short_help("t"); }
969 }
970
971 make_tmpdir($tdir);
972 main();
973 remove_tmpdir($tdir);
-
+ 48D9A73B6BC7AEBC3A70BFFF5BD8568DB21A641BD28D0042CEB0E0BCBC397AEDF7291670C4B4987ED952471D62F450FFBEBD1C9134E70EB040CABFC0637C3B3E
v/v_quick_start.txt
(0 . 0)(1 . 72)
978 ..::[ The Bitcoin Foundation: V Quick Start ]::..
979
980
981 Doc Version: 99994 K
982 Author: mod6
983 Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF
984
985 0x00]: Introduction
986
987 Welcome to V!
988
989 This document is intended for the advanced user. This will get you up and
990 running quickly with V.
991
992 0x01]: What's required?
993
994 0x010: perl 5.005 or greater
995 0x011: cpan | cpanm [CPAN | cpanminus]
996 0x012: Graph::Easy [Nice to have, not required]
997 0x013: graphviz [Nice to have, not required]
998 0x014: gpg [GnuPG]
999 0x015: wget
1000
1001 0x02]: Where do I get V ?
1002
1003 curl -s http://thebitcoin.foundation/v/V-20170317.tar.gz \
1004 -o V-20170317.tar.gz
1005 curl -s http://thebitcoin.foundation/v/V-20170317.tar.gz.mod6.sig \
1006 -o V-20170317.tar.gz.mod6.sig
1007
1008 gpg --keyserver pool.sks-keyservers.net \
1009 --recv-keys 0x027A8D7C0FB8A16643720F40721705A8B71EADAF
1010
1011 gpg --verify V-20170317.tar.gz.mod6.sig V-20170317.tar.gz
1012
1013 If the signature is good, now extract the archive.
1014
1015 tar -xf V-20170317.tar.gz
1016
1017 0x03]: How do I setup V?
1018
1019 First, set the executable bit on v.pl:
1020
1021 chmod +x v.pl
1022
1023 Next, create a WoT directory (V will look for '.wot' in the current working
1024 directory by default):
1025
1026 mkdir -p .wot
1027
1028 Then, place WoT pubkeys into the '.wot' directory. Name the pubkey files
1029 as such: <wotid>.asc
1030
1031 For example: mod6.asc
1032
1033 0x04]: It's my first time running V now what?
1034
1035 First, check the available signed mirrors:
1036
1037 ./v.pl m mirrors
1038
1039 Then run the intial sync of the vpatches and seals from a given mirror:
1040
1041 ./v.pl i http://thebitcoin.foundation
1042
1043 0x05]: Now that I've sync'd from a mirror, what's next?
1044
1045 The rest is up to you, either refer to the Users Guide for a detailed
1046 description of each option in V or just execute V and read the long
1047 help message:
1048
1049 ./v.pl help
-
+ 12CCA3D90B11AD346B6224E009E263BE37361B8EB80E523C3B3F694586AB4E057B07B191ECDABAF4F73DB778F1C23D7FC78241F48D1CB5E1DE566A7F1BEECBB0
v/v_users_manual.txt
(0 . 0)(1 . 536)
1054 ..::[ The Bitcoin Foundation: V Users Manual ]::..
1055
1056
1057 Doc Version: 99994 K
1058 Author: mod6
1059 Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF
1060
1061 0x00]: Introduction
1062
1063 Welcome to V!
1064
1065 This document is intended to be a users manual for mod6's perl implementation
1066 of V. Contained herein the user will find usage explanations and examples of
1067 the many options available.
1068
1069 0x01]: Getting Started
1070
1071 [ Check if perl is installed & version ]:
1072
1073 First, in order to execute the perl version of V, the user must have perl
1074 version 5.005 or greater installed on the local UNIX environment. Perl
1075 typically comes installed on many UNIX environments ahead of time, but just
1076 to be sure, do the following from the command prompt:
1077
1078 perl --version
1079
1080 The user should see a lengthy version message that starts with something
1081 like this:
1082
1083 `This is perl 5, version 18, subversion 2 (v5.18.2) ...'
1084
1085 If not, please install perl 5.005 or greater before going any further:
1086
1087 Ubuntu:
1088 apt-get install -y perl
1089
1090 Gentoo:
1091 emerge =perl-5.20.2.ebuild
1092
1093 [ Install CPAN ]:
1094
1095 If it is desired to at all use the graphing feature of V the user will need
1096 to install CPAN [ `cpan` or `cpanm` or on gentoo, `g-cpan` ] so that the
1097 Graph::Easy perl library can be installed.
1098
1099 Ubuntu:
1100
1101 apt-get install cpanminus
1102 cpanm -i Graph::Easy
1103
1104 Gentoo [x86-64]:
1105
1106 emerge g-cpan
1107
1108 [ NOTE: Copy the next nine lines exacty as they are presented here and ]
1109 [ then paste them into the shell. ]
1110
1111 cat <<EOF > /etc/portage/package.accept_keywords
1112 # required by perl-gcpan/JSON-MaybeXS-1.003005::x-g-cpan
1113 # required by JSON-MaybeXS (argument)
1114 =dev-perl/Test-Without-Module-0.180.0 ~amd64
1115 # required by perl-gcpan/Cpanel-JSON-XS-3.0115::x-g-cpan
1116 # required by Cpanel-JSON-XS (argument)
1117 =dev-perl/common-sense-3.730.0 ~amd64
1118 EOF
1119
1120 g-cpan -i Graph::Easy
1121
1122 [ Install GnuPG ]:
1123
1124 The user will need GnuPG installed locally to run V, if you already have
1125 this installed, skip this step.
1126
1127 Ubuntu:
1128 sudo apt-get install -y gnupg
1129
1130 [NOTE: 1.4.19 seems to be the oldest portage a recent gentoo ships with)]:
1131 Gentoo:
1132 emerge =gnupg-1.4.19
1133
1134 [ Install wget ]:
1135
1136 Many UNIX systems come with `wget` installed already, if yours does not,
1137 install it:
1138
1139 Ubuntu:
1140 sudo apt-get install -y wget
1141
1142 Gentoo:
1143 emerge wget
1144
1145 [ Install GraphViz ]:
1146
1147 In addition to Graph::Easy, if you wish to have V automatically build the
1148 SVG graph in an HTML output file for you from the Dot language output file,
1149 also output by V, you need to install GraphViz.
1150
1151 Ubuntu:
1152 sudo apt-get install -y graphviz
1153
1154 Gentoo:
1155 emerge -a graphviz
1156 etc-update [ enter -5 when prompted ]
1157 emerge -a graphviz [ Answer Yes at prompt ]
1158
1159 [ Download V Archive ]:
1160
1161 Now you must obtain the V archive & signature from:
1162
1163 http://thebitcoin.foundation/v/V-20170317.tar.gz
1164 http://thebitcoin.foundation/v/V-20170317.tar.gz.mod6.sig
1165
1166 Then check the PGP signatures supplied:
1167
1168 wget http://mod6.net/mod6.asc -O mod6.asc
1169 gpg --import mod6.asc
1170
1171 [ Key Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF ]
1172
1173 gpg --verify V-20170317.tar.gz.mod6.sig V-20170317.tar.gz
1174
1175 Then unpack the archive:
1176
1177 tar -xf V-20170317.tar.gz
1178
1179 [ Start V for the first time ]:
1180
1181 First, set the executable bit on v.pl:
1182
1183 chmod 0755 v.pl
1184
1185 Before you get any further, create a '.wot' directory (V looks for '.wot'
1186 in the current working directory by default) and populate it with PGP public
1187 keys manually. Name the pubkey files as such: <wotid>.asc
1188
1189 For example: mod6.asc
1190
1191 Now have V sync the required Seals and Patches directories from a signed
1192 mirror. To view the list of mirrors, run the following command, the output
1193 you'll see below.
1194
1195 ./v.pl m v_mirrors
1196 Mirrors signed by (mod6):
1197 http://thebitcoin.foundation
1198
1199 As stated from mirrors output we can use URL from The Bitcoin Foundation to
1200 sync V up-to-date with all the latest WoT entries (PGP Public Keys), VPatch
1201 Signatures (Seals) and Vpatches.
1202
1203 To begin this initial sync do the following:
1204
1205 ./v.pl i http://thebitcoin.foundation
1206
1207
1208 0x01]: V Usage
1209
1210 At this point the user has installed all of V's requirements, performed a
1211 lookup of available signed mirrors, and sync'd the WoT, Patches and Seals.
1212
1213 What follows are usages and definitions of V's options with examples.
1214
1215 A note about option syntax. Any option enclosed with parenthesis ( ) is
1216 required. The | separates any aliases of commands. Square brackets [ ]
1217 denote optional options. Angle brackets < > denote required arguments to
1218 a given command.
1219
1220 [ m | mirrors ]:
1221 Arguments:
1222 (<output_dir>)
1223
1224 The m or mirrors command is available to connect to the main V site:
1225 http://thebitcoin.foundation Here, V can connect and pull the list of
1226 available mirrors, signed by mirror administrators with L1 trust with
1227 assbot and are in good standing in the WoT. Ask mod6 about this if you
1228 want to run an authorized, signed mirror of V.
1229
1230 The mirrors command takes one required argument, an output directory for the
1231 list of mirrors and the signatures so V can verify the list.
1232
1233 Example:
1234 ./v.pl m v_mirrors
1235 Mirrors signed by (mod6):
1236 http://thebitcoin.foundation
1237
1238 [ i | init ]:
1239
1240 Arguments & Options:
1241 (mirror_url) [(<pdir> <sdir>)]
1242
1243 The i or init command is intended to be utilized the first time running V
1244 on an environment. It takes one required option, and two optional
1245 options. The required argument is a V mirror URL to sync from. Next, the
1246 user can choose to use the default Patches ('patches' in the current working
1247 directory) and Seals (.seals in the current working directory) directories
1248 by not setting the two <pdir> or <sdir> options -- only passing a mirror URL
1249 argument to the init command. If the user wishes to use their own named
1250 directories, simply pass in those arguements in the exact order specified.
1251
1252 Example:
1253 ./v.pl i http://thebitcoin.foundation
1254 Full vpatch sync complete to "/home/mod6/patches"
1255 Seal sync complete to "/home/mod6/.seals"
1256
1257 Example:
1258 ./v.pl i http://thebitcoin.foundation wot vpatches seals
1259 Full vpatch sync complete to "vpatches"
1260 Seal sync complete to "seals"
1261
1262 [ wd | wotdir ]:
1263
1264 Arguments:
1265 (<wotdir>)
1266
1267 The wd or wotdir command is available to point V at a specific WoT
1268 directory rather than the default: '.wot' (in the current working directory)
1269 There is one required argument: a WoT directory.
1270
1271 Example case, only mod6.asc exists in wot2:
1272 ./v.pl f wd wot2
1273 genesis.vpatch (mod6)
1274 bitcoin-asciilifeform.1.vpatch (mod6)
1275 rm_rf_upnp.vpatch (mod6)
1276 ...
1277
1278 [ pd | patchdir ]:
1279
1280 Arguments:
1281 (<patchdir>)
1282
1283 The pd or patchdir command is available to point V at a specific patch
1284 directory rather than the default: 'patches', in V's present working
1285 directory. There is one required argument: a vpatches directory.
1286
1287 Example case, only genesis.vpatch exists in patches2:
1288 ./v.pl f pd patches2
1289 genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1290
1291 [ sd | sealdir ]:
1292
1293 Arguments:
1294 (<sealdir>)
1295
1296 The sd or sealdir command is available to point V at a specific seal
1297 directory rather than the default: '.seals' (in the current working
1298 directory)
1299 There is one required argument: a seals directory.
1300
1301 Example case, only seals created by mod6 exist in seal2:
1302 ./v.pl f sd seals2/
1303 genesis.vpatch (mod6)
1304 bitcoin-asciilifeform.1.vpatch (mod6)
1305 rm_rf_upnp.vpatch (mod6)
1306 ...
1307
1308 [ w | wot ]:
1309
1310 Options:
1311 [ finger ]
1312
1313 The w or wot command will build a list of WoT entities eligable for
1314 creating seals for approved vpatches. If a specific vpatch has not
1315 been signed by a WoT entity, it is considered a 'WILD' vpatch, and will be
1316 ignored. A vpatch must be signed by both Co-Chairs of The Bitcoin Foundation
1317 to be considered approved for release.
1318
1319 Example:
1320 ./v.pl w
1321 asciilifeform:17215D118B7239507FAFED98B98228A001ABFFC7:Stanislav Datskovskiy <stas@loper-os.org>
1322 ben_vulpes:4F7907942CA8B89B01E25A762AFA1A9FD2D031DA:Ben Vulpes <benkay@gmail.com>
1323 mircea_popescu:6160E1CAC8A3C52966FD76998A736F0E2FB7B452:Mircea Popescu (Acest articol are apriori avantajul aliteralitatii alaturi.) <office@polimedia.us>
1324 mod6:027A8D7C0FB8A16643720F40721705A8B71EADAF:mod6 (mod6) <modsix@gmail.com>
1325 punkman:F28E0095843B91CB22E7D65533588BE08B232B13:punkman
1326 trinque:FC66C0C5D98C42A1D4A98B6B42F9985AFAB953C4:Michael Trinque <mike@trinque.org>
1327
1328 ./v.pl w finger
1329 asciilifeform-B98228A001ABFFC7:17215D118B7239507FAFED98B98228A001ABFFC7:Stanislav Datskovskiy <stas@loper-os.org>
1330 ben_vulpes-2AFA1A9FD2D031DA:4F7907942CA8B89B01E25A762AFA1A9FD2D031DA:Ben Vulpes <benkay@gmail.com>
1331 mircea_popescu-8A736F0E2FB7B452:6160E1CAC8A3C52966FD76998A736F0E2FB7B452:Mircea Popescu (Acest articol are apriori avantajul aliteralitatii alaturi.) <office@polimedia.us>
1332 mod6-721705A8B71EADAF:027A8D7C0FB8A16643720F40721705A8B71EADAF:mod6 (mod6) <modsix@gmail.com>
1333 punkman-33588BE08B232B13:F28E0095843B91CB22E7D65533588BE08B232B13:punkman
1334 trinque-42F9985AFAB953C4:FC66C0C5D98C42A1D4A98B6B42F9985AFAB953C4:Michael Trinque <mike@trinque.org>
1335
1336 [ r | roots ]:
1337
1338 The r or roots command takes no options or arguments, unless a different
1339 pd or patchdir is specified. It simply traverses the vpatch directories
1340 contained vpatches and returns any root vpatches found in the topological
1341 order.
1342
1343 Examples:
1344 ./v.pl r
1345 Root: genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1346
1347 Examples:
1348 ./v.pl r pd patches2
1349 Root: genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1350
1351 [ l | leafs ]:
1352
1353 The l or leafs command takes no options or arguments, unless a different
1354 pd or patchdir is specified. It simply traverses the vpatch directories
1355 contained vpatches and returns any leaf vpatches found in the topological
1356 order.
1357
1358 Examples:
1359 ./v.pl l
1360 Leaf: asciilifeform_add_verifyall_option.vpatch (asciilifeform, mod6)
1361 Leaf: asciilifeform_maxint_locks_corrected.vpatch (asciilifeform, mod6)
1362
1363 Example case, only genesis.vpatch exists in patches2:
1364 ./v.pl l pd patches2
1365 Leaf: genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1366
1367 [ f | flow ]:
1368
1369 The f or flow command prints a topoligical flow of vpatches based on
1370 precedence. By default will look for the 'patches' directory in the present
1371 working directory of V and print the flow to stdout.
1372
1373 Example:
1374 ./v.pl f
1375 genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1376 bitcoin-asciilifeform.1.vpatch (asciilifeform, mod6)
1377 rm_rf_upnp.vpatch (asciilifeform, mod6)
1378 bitcoin-asciilifeform.3-turdmeister-alert-snip.vpatch (asciilifeform, mod6)
1379 bitcoin-asciilifeform.2-https_snipsnip.vpatch (asciilifeform, mod6)
1380 bitcoin-asciilifeform.4-goodbye-win32.vpatch (asciilifeform, mod6)
1381 asciilifeform_dnsseed_snipsnip.vpatch (asciilifeform, mod6)
1382 asciilifeform_zap_hardcoded_seeds.vpatch (asciilifeform, mod6)
1383 asciilifeform-kills-integer-retardation.vpatch (asciilifeform, mod6)
1384 asciilifeform_zap_showmyip_crud.vpatch (asciilifeform, mod6)
1385 asciilifeform_dns_thermonyukyoolar_kleansing.vpatch (asciilifeform, mod6)
1386 asciilifeform_and_now_we_have_block_dumper_corrected.vpatch (asciilifeform, mod6)
1387 mod6_fix_dumpblock_params.vpatch (asciilifeform, mod6)
1388 bitcoin-v0_5_3_1-static_makefile_v002.8.vpatch (asciilifeform, mod6)
1389 bitcoin-v0_5_3_1-rev_bump.7.vpatch (asciilifeform, mod6)
1390 asciilifeform_ver_now_5_4_and_irc_is_gone_and_now_must_give_ip.vpatch (asciilifeform, mod6)
1391 asciilifeform_orphanage_thermonuke.vpatch (asciilifeform, mod6)
1392 asciilifeform_and_now_we_have_eatblock.vpatch (asciilifeform, mod6)
1393 bitcoin-v0_5_3-db_config.6.vpatch (asciilifeform, mod6)
1394 asciilifeform_tx-orphanage_amputation.vpatch (asciilifeform, mod6)
1395 asciilifeform_maxint_locks_corrected.vpatch (asciilifeform, mod6)
1396 asciilifeform_lets_lose_testnet.vpatch (asciilifeform, mod6)
1397 asciilifeform_add_verifyall_option.vpatch (asciilifeform, mod6)
1398
1399 Example case, only genesis.vpatch exists in patches2:
1400 ./v.pl f pd patches2
1401 genesis.vpatch (asciilifeform, mircea_popescu, mod6, trinque)
1402
1403 [ p | press ]:
1404
1405 Arguments:
1406 (<press_dir> <head>)
1407
1408 The p or press command is available to apply vpatches up through <head> in
1409 topological order (see flow command) to an output directory <press_dir>.
1410 There are two required arguments; an output directory for applied patches
1411 <press_dir> and a vpatch <head> as the tip of the tree to press up through.
1412 By default, no output is shown; however if the user supplies `v' or
1413 `verbose' directly after the p or press command then the output from the
1414 patching applcation process will be directed to stdout.
1415
1416 Example:
1417 ./v.pl p press_output genesis.vpatch
1418
1419 Example:
1420 ./v.pl p verbose press_verbose genesis.vpatch
1421 genesis.vpatch
1422 patching file bitcoin/.gitignore
1423 patching file bitcoin/COPYING
1424 patching file bitcoin/src/base58.h
1425 patching file bitcoin/src/bignum.h
1426 patching file bitcoin/src/bitcoinrpc.cpp
1427 patching file bitcoin/src/bitcoinrpc.h
1428 patching file bitcoin/src/checkpoints.cpp
1429 patching file bitcoin/src/checkpoints.h
1430 patching file bitcoin/src/crypter.cpp
1431 patching file bitcoin/src/crypter.h
1432 patching file bitcoin/src/db.cpp
1433 patching file bitcoin/src/db.h
1434 patching file bitcoin/src/headers.h
1435 patching file bitcoin/src/init.cpp
1436 ...
1437
1438 [ ss | sync-seals ]:
1439
1440 Arguments:
1441 (<mirror_url> <sdir>)
1442
1443 The ss or sync-seals command is avilable to allow the user to sync seal to
1444 an alternative directory. Two arguments are required; the <mirror_url>
1445 from which to sync and the alternative or existing seals directory <sdir>.
1446
1447 Example:
1448 ./v.pl ss http://thebitcoin.foundation seals2
1449 Seal sync complete to "seals2"
1450
1451 [ sv | sync-vpatches ]:
1452
1453 Arguments:
1454 (<mirror_url> <pdir> <vpatches>... )
1455
1456 The sv or sync-vpatches command is availabe to allow the user to sync one or
1457 more individual vpatches to a alternative output directory. Three arguments
1458 are required; the <mirror_url> from which to sync, the alternative or
1459 existing directory <pdir> and one or more <vpatches>.
1460
1461 Example case, sync one vpatch to an existing patches directory:
1462 ./v.pl sv http://thebitcoin.foundation patches genesis.vpatch
1463 genesis.vpatch sync complete to "patches"
1464
1465 Example case, sync more than one vpatch to an alternative patches directory:
1466 ./v.pl sv http://thebitcoin.foundation patches2 genesis.vpatch rm_rf_upnp.vpatch
1467 genesis.vpatch sync complete to "patches2"
1468 rm_rf_upnp.vpatch sync complete to "patches2"
1469
1470 [ sa | sync-all-vpatches ]:
1471
1472 Arguments:
1473 (<mirror_url> <pdir>)
1474
1475 The sa or sync-all-vpatches command is avilable to allow the user to sync
1476 all vpatches from a given mirror to an alternative output directory. Two
1477 arguments are required; the <mirror_url> from which to sync and the
1478 alternative or existing patches directory <pdir>.
1479
1480 Example case, sync all vpatches to the pre-existing patches directory:
1481 ./v.pl sa http://thebitcoin.foundation patches
1482 Full vpatch sync complete to "patches"
1483
1484 Example case, sync all vpatches to an alternative patches directory:
1485 ./v.pl sa http://thebitcoin.foundation patches2
1486 Full vpatch sync complete to "patches2"
1487
1488 [ se | sync-everything ]:
1489
1490 Arguments:
1491 (<mirror_url> <pdir> <sdir>)
1492
1493 The se or sync-everything command is available to allow the user to sync
1494 all patches and seals from a given mirror to either existing or alternative
1495 directories. Three arguments are required; the <mirror_url> from which to
1496 sync, the existing or alternative output patches directory <pdir>, and the
1497 existing or alternative seals directory <sdir>.
1498
1499 ./v.pl se http://thebitcoin.foundation patches2 seals2
1500 Full vpatch sync complete to "patches2"
1501 Seal sync complete to "seals2"
1502
1503 [ a | ante | antecedents ]:
1504
1505 Arguments:
1506 (<vpatch>)
1507
1508 The a or ante or antecedents command is available to allow the user to view
1509 the antecedents of a given vpatch. One argument is required, the name of a
1510 <vpatch>.
1511
1512 Example:
1513 ./v.pl a mod6_fix_dumpblock_params.vpatch
1514 Antecedent: asciilifeform_and_now_we_have_block_dumper_corrected.vpatch \
1515 (asciilifeform, mod6) [ a/bitcoin/src/bitcoinrpc.cpp ]
1516
1517 Example case, examine the antecedents of a given vpatch from an alternative
1518 directory:
1519 ./v.pl a asciilifeform_zap_showmyip_crud.vpatch pd patches2
1520 Antecedent: asciilifeform_zap_hardcoded_seeds.vpatch (asciilifeform, mod6) \
1521 [ a/bitcoin/src/net.cpp ]
1522
1523 [ d | desc | descendants ]:
1524
1525 Arguments:
1526 (<vpatch>)
1527
1528 The d or desc or descendants command is available to allow the user to view
1529 the descendants of a given <vpatch>. One argument is required, the name of
1530 a <vpatch>.
1531
1532 Example:
1533 ./v.pl d mod6_fix_dumpblock_params.vpatch
1534 Descendant: asciilifeform_and_now_we_have_eatblock.vpatch \
1535 (asciilifeform, mod6) [ a/bitcoin/src/bitcoinrpc.cpp ]
1536
1537 Example case, examine the descendants of a given vpatch from an alternative
1538 directory:
1539 ./v.pl d asciilifeform_zap_showmyip_crud.vpatch pd patches2
1540 Descendant: asciilifeform_dns_thermonyukyoolar_kleansing.vpatch \
1541 (asciilifeform, mod6) [ a/bitcoin/src/net.cpp ]
1542
1543 [ o | origin ]:
1544
1545 Arguments:
1546 (<sha512_hash>)
1547
1548 The o or origin command is avaliable to allow the user to pass a sha512
1549 hash and view where the given hash originated in the source tree.
1550
1551 [ g | graph ]:
1552
1553 Arguments & Options:
1554 (<output_dotfile> [<output_svg_html_file>])
1555
1556 The g or graph command is available to produce a topoligical flow graph in
1557 SVG format. The command has a required argument, the <output_dotfile>.
1558 The output Dot language file can be used to generate the SVG HTML output
1559 file with the `dot` binary. To produce the output Dot language file, the
1560 perl library Graph::Easy must be installed on the local environment.
1561 The optional command is given as a name for the <output_svg_html_file>.
1562 If 'graphviz' is installed on the local environment, then the `dot` binary
1563 should be available for V to invoke and generate the SVG HTML output for
1564 the user automatically. If it is not possible for the user to install
1565 'graphviz' on the local environment for whatever reason, the Dot language
1566 output file can be copied to a seperate environment where 'graphviz' can be
1567 installed. A command like this is used to generate the SVG HTML output
1568 with the `dot` binary: `dot -Tsvg v-graph.dot > v-graph.html`.
1569
1570 Example:
1571 ./v.pl g vpatch.dot vpatch-graph.html
1572 Printed Graphviz dot file to vpatch.dot
1573 Executed `dot` and built svg html output file: vpatch-graph.html
1574
1575 Example case, build a graph from an alternative WoT, Patches and Seals
1576 directory:
1577 ./v.pl g vpatch-graph2.dot vpatch-graph2.html wd wot2 pd patches2 sd seals2
1578 Printed Graphviz dot file to vpatch-graph2.dot
1579 Executed `dot` and built svg html output file: vpatch-graph2.html
1580
1581 [ v | version ]:
1582
1583 The v or version command simply prints the current version of V to stdout.
1584 This command takes no options or arguments.
1585
1586 [ h | ? | help ]:
1587
1588 The h or ? or help command will print a longer, more verbose help message
1589 to stdout. This command takes no options or arguments.