raw
v_mod6_genesis          1 #!/usr/bin/perl
v_mod6_genesis 2
v_mod6_99993 3 # (C) 2014 - 2018 The Bitcoin Foundation. You do not have, nor can you ever
v_mod6_genesis 4 # acquire the right to use, copy or distribute this software ; Should you use
v_mod6_genesis 5 # this software for any purpose, or copy and distribute it to anyone or in any
v_mod6_genesis 6 # manner, you are breaking the laws of whatever soi-disant jurisdiction, and
v_mod6_genesis 7 # you promise to continue doing so for the indefinite future. In any case,
v_mod6_genesis 8 # please always : read and understand any software ; verify any PGP signatures
v_mod6_genesis 9 # that you use - for any purpose.
v_mod6_genesis 10
v_mod6_genesis 11 use strict;
v_mod6_genesis 12
v_mod6_99993 13 my $version = "99993 K ";
v_mod6_genesis 14
v_mod6_99993 15 my $tdir = "";
v_mod6_genesis 16
v_mod6_genesis 17 my $graph;
v_mod6_genesis 18 my %wot = ();
v_mod6_genesis 19 my %map = ();
v_mod6_genesis 20 my %tmp_map = ();
v_mod6_genesis 21 my %banners = ();
v_mod6_99993 22 my %ante_map = ();
v_mod6_genesis 23 my %desc_map = ();
v_mod6_genesis 24 my %vp_map = ();
v_mod6_genesis 25
v_mod6_genesis 26 my ($pdir, $sdir, $wdir) = "";
v_mod6_genesis 27 my (@pfiles, @sfiles, @wfiles) = ();
v_mod6_genesis 28
v_mod6_99993 29 my @dep_bins = ("cat", "echo", "gpg", "ls", "mkdir", "patch", "pwd",
v_mod6_99993 30 "rm", "sha512sum", "sort", "wget", "which", "mktemp");
v_mod6_99993 31
v_mod6_99993 32 sub check_required_bins {
v_mod6_99993 33 my (@bins) = @_;
v_mod6_99993 34
v_mod6_99993 35 foreach my $bin (@bins) {
v_mod6_99993 36 my $res = `command -v $bin >&1`; chomp($res);
v_mod6_99993 37 death("Dependent program not found! : $bin\n") if $res eq "";
v_mod6_99993 38 }
v_mod6_genesis 39 }
v_mod6_genesis 40
v_mod6_genesis 41 sub get_pwd {
v_mod6_genesis 42 my $pwd = `pwd`; chomp($pwd);
v_mod6_genesis 43 return $pwd;
v_mod6_genesis 44 }
v_mod6_genesis 45
v_mod6_genesis 46 sub set_files {
v_mod6_genesis 47 my ($dir) = @_;
v_mod6_genesis 48 if(!-d $dir) {
v_mod6_genesis 49 my $msg = "$dir directory does not exist.\n" .
v_mod6_genesis 50 "See 'init' or 'sync' commands in 'help'.\n";
v_mod6_genesis 51 death($msg);
v_mod6_genesis 52 }
v_mod6_genesis 53 my @a = `ls $dir | sort`;
v_mod6_genesis 54 return wash(@a);
v_mod6_genesis 55 }
v_mod6_genesis 56
v_mod6_genesis 57 sub wash { my (@a)=@_; my @b; foreach(@a) {chomp($_); push @b, $_;} return @b; }
v_mod6_genesis 58
v_mod6_genesis 59 sub init {
v_mod6_genesis 60 my ($URL, $pd, $sd) = @_;
v_mod6_genesis 61
v_mod6_genesis 62 if($URL && $pd && $sd) {
v_mod6_genesis 63 if(!-d $pd) { `mkdir -p $pd`; sync_all_vpatches($URL, $pd); }
v_mod6_genesis 64 else { print "$pd dir exists! Skipping initial Vpatch sync\n"; }
v_mod6_genesis 65 if(!-d $sd) { `mkdir -p $sd`; sync_seals($URL, $sd); }
v_mod6_genesis 66 else { print "$sd dir exists! Skipping initial Seal sync\n"; }
v_mod6_genesis 67 }
v_mod6_genesis 68 }
v_mod6_genesis 69
v_mod6_genesis 70 sub build_wot {
v_mod6_genesis 71 my $uid, my $banner, my $keyid, my $fp;
v_mod6_genesis 72 foreach my $pubkey (@wfiles) {
v_mod6_genesis 73 my $import = "gpg --homedir $tdir --logger-fd 1 --keyid-format=long " .
v_mod6_genesis 74 "--import $wdir/$pubkey 2> /dev/null";
v_mod6_genesis 75 my $res = `$import`;
v_mod6_genesis 76 $uid = $1 if $pubkey =~ /(.*)\.asc/; chomp($uid);
v_mod6_genesis 77 $banner = $1 if $res =~ /\"(.*)\"/; chomp($banner);
v_mod6_genesis 78 $keyid = $1 if $res =~ /key (.*)\:/; chomp($keyid);
v_mod6_genesis 79 my $res_fp = `gpg --homedir $tdir --logger-fd 1 --fingerprint $keyid`;
v_mod6_genesis 80 $fp = $1 if $res_fp =~ /Key fingerprint = (.*)/; $fp =~ s/\s+//g;
v_mod6_genesis 81 $wot{$uid} = { fp => $fp, banner => $banner };
v_mod6_genesis 82 }
v_mod6_genesis 83 }
v_mod6_genesis 84
v_mod6_genesis 85 sub validate_seals {
v_mod6_genesis 86 my $seal_key, my $seal_signatory, my $uid, my $fp, my $patch, my %sig;
v_mod6_genesis 87 foreach my $patch (@pfiles) {
v_mod6_genesis 88 foreach my $seal (@sfiles) {
v_mod6_genesis 89 $seal_key = $1 if $seal =~ /^(.*)\..*\..*$/;
v_mod6_genesis 90 $seal_signatory = $1 if $seal =~ /^.*\.(.*)\..*$/;
v_mod6_genesis 91 if($patch =~ /^$seal_key$/) {
v_mod6_genesis 92 if(exists $wot{$seal_signatory}) {
v_mod6_genesis 93 if(not exists $banners{$patch} && $patch ne "") {
v_mod6_genesis 94 $banners{$patch} = $patch;
v_mod6_genesis 95 %sig = ();
v_mod6_genesis 96 }
v_mod6_genesis 97 my $verify = "gpg --homedir $tdir --logger-fd 1 --verify $sdir/$seal " .
v_mod6_genesis 98 "$pdir/$patch";
v_mod6_genesis 99 my @res = `$verify`;
v_mod6_genesis 100 foreach my $r (@res) {
v_mod6_genesis 101 $fp = $1 if $r =~ /Primary key fingerprint: (.*)/; $fp =~ s/\s+//g;
v_mod6_genesis 102 foreach my $uidkey (sort keys %wot) {
v_mod6_genesis 103 if($wot{$uidkey}{fp} eq $fp) {
v_mod6_genesis 104 $uid = $uidkey;
v_mod6_genesis 105 last;
v_mod6_genesis 106 }
v_mod6_genesis 107 }
v_mod6_genesis 108 }
v_mod6_genesis 109 my $verified = "";
v_mod6_genesis 110 foreach my $r (@res) {
v_mod6_genesis 111 if($r =~ /Good signature/ && $uid ne "") {
v_mod6_genesis 112 $sig{$wot{$uid}{fp}} = $uid;
v_mod6_genesis 113 $banners{$patch} = {%sig};
v_mod6_genesis 114 $verified = "true";
v_mod6_genesis 115 last;
v_mod6_genesis 116 }
v_mod6_genesis 117 }
v_mod6_genesis 118 if($verified ne "true") {
v_mod6_genesis 119 my $border = "-----------------------------------------" .
v_mod6_genesis 120 "-----------------------------------------";
v_mod6_genesis 121 print "$border\n";
v_mod6_genesis 122 print "WARNING: $seal is an INVALID seal for $patch!\n";
v_mod6_genesis 123 my $msg = "Check that this user is in your WoT.\n" .
v_mod6_genesis 124 "Otherwise remove the invalid seal from your SEALS directory.";
v_mod6_genesis 125 print "$msg\n";
v_mod6_genesis 126 print "$border\n";
v_mod6_genesis 127 death();
v_mod6_genesis 128 }
v_mod6_genesis 129 $verified = "";
v_mod6_genesis 130 }
v_mod6_genesis 131 }
v_mod6_genesis 132 }
v_mod6_genesis 133 }
v_mod6_genesis 134 }
v_mod6_genesis 135
v_mod6_genesis 136 sub build_map {
v_mod6_genesis 137 my %vpdata;
v_mod6_genesis 138 @pfiles = ();
v_mod6_genesis 139 foreach my $vpatch (keys %banners) {
v_mod6_genesis 140 push @pfiles, $vpatch;
v_mod6_genesis 141 }
v_mod6_genesis 142 foreach my $pfile (@pfiles) {
v_mod6_genesis 143 $map{$pfile} = $pfile;
v_mod6_genesis 144 my @patch = `cat $pdir/$pfile`;
v_mod6_genesis 145 my $src_file = "", my $ante_hash = "", my $desc_hash = "";
v_mod6_genesis 146 foreach my $p (@patch) {
v_mod6_genesis 147 $src_file = $1, $ante_hash = $2 if $p =~ /^--- (.*) (.*)/;
v_mod6_genesis 148 $desc_hash = $1 if $p =~ /^\+\+\+ .* (.*)/;
v_mod6_genesis 149 if($src_file && $ante_hash && $desc_hash) {
v_mod6_genesis 150 death("$pfile is an invalid vpatch!\n") if $ante_hash eq $desc_hash;
v_mod6_genesis 151 $vpdata{$src_file} = { a => $ante_hash, b => $desc_hash };
v_mod6_genesis 152 $map{$pfile} = {%vpdata};
v_mod6_genesis 153 $src_file = "", $ante_hash = "", $desc_hash = "";
v_mod6_genesis 154 }
v_mod6_genesis 155 }
v_mod6_genesis 156 death("Error! $pfile is an invalid vpatch file.\n") if !%vpdata;
v_mod6_genesis 157 %vpdata = ();
v_mod6_genesis 158 }
v_mod6_genesis 159 return %map;
v_mod6_genesis 160 }
v_mod6_genesis 161
v_mod6_genesis 162 sub roots {
v_mod6_genesis 163 my @roots = ();
v_mod6_genesis 164 my $is_root = "false";
v_mod6_genesis 165 foreach my $vpatch (keys %map) {
v_mod6_genesis 166 my %ante = antecedents($vpatch);
v_mod6_genesis 167 if(!%ante) {
v_mod6_genesis 168 foreach my $src_file_name (keys %{$map{$vpatch}}) {
v_mod6_genesis 169 if($map{$vpatch}{$src_file_name}->{a} eq "false") {
v_mod6_genesis 170 $is_root = "true";
v_mod6_genesis 171 next;
v_mod6_genesis 172 } else {
v_mod6_genesis 173 $is_root = "false";
v_mod6_genesis 174 last;
v_mod6_genesis 175 }
v_mod6_genesis 176 }
v_mod6_genesis 177 push @roots, $vpatch if $is_root eq "true";
v_mod6_genesis 178 }
v_mod6_genesis 179 }
v_mod6_genesis 180 return @roots;
v_mod6_genesis 181 }
v_mod6_genesis 182
v_mod6_genesis 183 sub leafs {
v_mod6_genesis 184 my @leafs;
v_mod6_genesis 185 foreach my $vpatch (keys %map) {
v_mod6_genesis 186 my %desc = descendants($vpatch);
v_mod6_genesis 187 push @leafs, $vpatch if !%desc;
v_mod6_genesis 188 }
v_mod6_genesis 189 return @leafs;
v_mod6_genesis 190 }
v_mod6_genesis 191
v_mod6_genesis 192 sub traverse_desc {
v_mod6_genesis 193 my (%st) = @_;
v_mod6_genesis 194 my %desc;
v_mod6_genesis 195 foreach my $k (keys %map) {
v_mod6_genesis 196 my @tmp = ();
v_mod6_genesis 197 foreach my $src_file_name (keys %{$map{$k}}) {
v_mod6_genesis 198 my $src_file = $map{$k}{$src_file_name};
v_mod6_genesis 199 foreach my $sf_name (keys %st) {
v_mod6_genesis 200 my $sf = $st{$sf_name};
v_mod6_genesis 201 if($src_file_name eq $sf_name &&
v_mod6_genesis 202 $src_file->{a} eq $sf->{b} &&
v_mod6_genesis 203 $src_file->{a} ne "false") {
v_mod6_genesis 204 push @tmp, $sf_name;
v_mod6_genesis 205 $desc{$k} = [@tmp];
v_mod6_genesis 206 }
v_mod6_genesis 207 }
v_mod6_genesis 208 }
v_mod6_genesis 209 }
v_mod6_genesis 210 return %desc;
v_mod6_genesis 211 }
v_mod6_genesis 212
v_mod6_genesis 213 sub traverse_ante {
v_mod6_genesis 214 my (%st) = @_;
v_mod6_genesis 215 my %ante;
v_mod6_genesis 216 foreach my $k (keys %map) {
v_mod6_genesis 217 my @tmp = ();
v_mod6_genesis 218 foreach my $src_file_name (keys %{$map{$k}}) {
v_mod6_genesis 219 my $src_file = $map{$k}{$src_file_name};
v_mod6_genesis 220 foreach my $sf_name (keys %st) {
v_mod6_genesis 221 my $sf = $st{$sf_name};
v_mod6_genesis 222 if($src_file_name eq $sf_name &&
v_mod6_genesis 223 $src_file->{b} eq $sf->{a} &&
v_mod6_genesis 224 $src_file->{b} ne "false") {
v_mod6_genesis 225 push @tmp, $sf_name;
v_mod6_genesis 226 $ante{$k} = [@tmp];
v_mod6_genesis 227 }
v_mod6_genesis 228 }
v_mod6_genesis 229 }
v_mod6_genesis 230 }
v_mod6_genesis 231 return %ante;
v_mod6_genesis 232 }
v_mod6_genesis 233
v_mod6_genesis 234 sub search_map {
v_mod6_genesis 235 my ($search_key) = @_;
v_mod6_genesis 236 if(exists $map{$search_key}) {
v_mod6_genesis 237 return %{$map{$search_key}};
v_mod6_genesis 238 } else {
v_mod6_genesis 239 death("Error! Could not find vpatch \"$search_key\" in $pdir\n");
v_mod6_genesis 240 }
v_mod6_genesis 241 }
v_mod6_genesis 242
v_mod6_genesis 243 sub antecedents {
v_mod6_genesis 244 my ($vpatch) = @_;
v_mod6_genesis 245 return traverse_ante(search_map($vpatch));
v_mod6_genesis 246 }
v_mod6_genesis 247
v_mod6_genesis 248 sub descendants {
v_mod6_genesis 249 my ($vpatch) = @_;
v_mod6_genesis 250 return traverse_desc(search_map($vpatch));
v_mod6_genesis 251 }
v_mod6_genesis 252
v_mod6_genesis 253 sub get_signatories {
v_mod6_genesis 254 my ($vpatch) = @_;
v_mod6_genesis 255 my @sigs;
v_mod6_genesis 256 foreach my $k (keys %banners) {
v_mod6_genesis 257 foreach my $fp (keys %{$banners{$k}}) {
v_mod6_genesis 258 my $uid = $banners{$k}{$fp};
v_mod6_genesis 259 push @sigs, $uid if $vpatch eq $k;
v_mod6_genesis 260 }
v_mod6_genesis 261 }
v_mod6_genesis 262 push @sigs, "WILD" if !@sigs;
v_mod6_genesis 263 return "(" . join(', ', sort @sigs) . ")";
v_mod6_genesis 264 }
v_mod6_genesis 265
v_mod6_genesis 266 sub build_flow {
v_mod6_genesis 267 my @flow = ();
v_mod6_genesis 268 my @roots = roots();
v_mod6_genesis 269 %tmp_map = %map;
v_mod6_genesis 270 foreach my $root (@roots) {
v_mod6_genesis 271 my %desc = descendants($root);
v_mod6_genesis 272 if(%desc) {
v_mod6_genesis 273 $desc_map{$root} = [keys %desc];
v_mod6_genesis 274 get_all_descendant_nodes(sort keys %desc);
v_mod6_genesis 275 verify_ante($root);
v_mod6_genesis 276 } else {
v_mod6_genesis 277 $desc_map{$root} = [];
v_mod6_genesis 278 }
v_mod6_genesis 279 }
v_mod6_genesis 280 @flow = toposort(%desc_map);
v_mod6_genesis 281 %map = scrub_map(@flow);
v_mod6_99993 282 return reverse @flow;
v_mod6_99993 283 }
v_mod6_99993 284
v_mod6_99993 285 sub calc_press_path {
v_mod6_99993 286 my ($head) = @_;
v_mod6_99993 287 traverse_press_path($head);
v_mod6_99993 288 return toposort(%ante_map);
v_mod6_99993 289 }
v_mod6_99993 290
v_mod6_99993 291 sub traverse_press_path {
v_mod6_99993 292 my ($vp) = @_;
v_mod6_99993 293
v_mod6_99993 294 my %ante = antecedents($vp);
v_mod6_99993 295
v_mod6_99993 296 if(%ante) {
v_mod6_99993 297 $ante_map{$vp} = [keys %ante];
v_mod6_99993 298 foreach my $a (keys %ante) {
v_mod6_99993 299 traverse_press_path($a);
v_mod6_99993 300 }
v_mod6_99993 301 } else {
v_mod6_99993 302 $ante_map{$vp} = [];
v_mod6_99993 303 }
v_mod6_genesis 304 }
v_mod6_genesis 305
v_mod6_genesis 306 sub scrub_map {
v_mod6_genesis 307 my (@flow) = @_;
v_mod6_genesis 308 foreach my $k (keys %tmp_map) {
v_mod6_genesis 309 if(!grep {/$k/} @flow) { delete $tmp_map{$k} if exists $tmp_map{$k}; }
v_mod6_genesis 310 }
v_mod6_genesis 311 return %tmp_map;
v_mod6_genesis 312 }
v_mod6_genesis 313
v_mod6_genesis 314 sub verify_ante {
v_mod6_genesis 315 my (@vpatch) = @_;
v_mod6_genesis 316 my %desc = ();
v_mod6_genesis 317 foreach my $vp (@vpatch) {
v_mod6_genesis 318 %desc = descendants($vp);
v_mod6_genesis 319 if(%desc) {
v_mod6_genesis 320 foreach my $a (sort keys %desc) {
v_mod6_genesis 321 check_ante($a);
v_mod6_genesis 322 }
v_mod6_genesis 323 }
v_mod6_genesis 324 }
v_mod6_genesis 325 if(%desc) {
v_mod6_genesis 326 verify_ante(sort keys %desc);
v_mod6_genesis 327 }
v_mod6_genesis 328 }
v_mod6_genesis 329
v_mod6_genesis 330 sub check_ante {
v_mod6_genesis 331 my ($vp) = @_;
v_mod6_genesis 332 my @curr_node_edge_hashes = ();
v_mod6_genesis 333 my @verified_hashes = ();
v_mod6_genesis 334 my %ante = antecedents($vp);
v_mod6_genesis 335 foreach my $curr_node_edge (keys %{$tmp_map{$vp}}) {
v_mod6_genesis 336 if($tmp_map{$vp}{$curr_node_edge}->{a} ne "false") {
v_mod6_genesis 337 push @curr_node_edge_hashes, $tmp_map{$vp}{$curr_node_edge}->{a};
v_mod6_genesis 338 }
v_mod6_genesis 339 foreach my $ante_node (keys %ante) {
v_mod6_genesis 340 foreach my $ante_node_edge (keys %{$tmp_map{$ante_node}}) {
v_mod6_genesis 341 next if $curr_node_edge ne $ante_node_edge;
v_mod6_genesis 342 if($tmp_map{$vp}{$curr_node_edge}->{a} eq
v_mod6_genesis 343 $tmp_map{$ante_node}{$ante_node_edge}->{b}) {
v_mod6_genesis 344 push @verified_hashes, $tmp_map{$vp}{$curr_node_edge}->{a};
v_mod6_genesis 345 }
v_mod6_genesis 346 }
v_mod6_genesis 347 }
v_mod6_genesis 348 }
v_mod6_genesis 349 if(@curr_node_edge_hashes != @verified_hashes) {
v_mod6_genesis 350 remove_desc($vp);
v_mod6_genesis 351 }
v_mod6_genesis 352 }
v_mod6_genesis 353
v_mod6_genesis 354 sub remove_desc {
v_mod6_genesis 355 my (@vp) = @_;
v_mod6_genesis 356 my %desc = ();
v_mod6_genesis 357 foreach my $v (@vp) {
v_mod6_genesis 358 delete $desc_map{$v} if exists $desc_map{$v};
v_mod6_genesis 359 delete $tmp_map{$v} if exists $tmp_map{$v};
v_mod6_genesis 360 my %desc = descendants($v);
v_mod6_genesis 361 next if !%desc;
v_mod6_genesis 362 foreach my $d (keys %desc) {
v_mod6_genesis 363 foreach my $dkeys (keys %desc_map) {
v_mod6_genesis 364 my @tmp = @{$desc_map{$dkeys}};
v_mod6_genesis 365 if(@tmp) {
v_mod6_genesis 366 my $offset = 0;
v_mod6_genesis 367 foreach my $t (@tmp) {
v_mod6_genesis 368 if($t eq $d) {
v_mod6_genesis 369 splice @tmp, $offset, 1;
v_mod6_genesis 370 }
v_mod6_genesis 371 $offset++;
v_mod6_genesis 372 }
v_mod6_genesis 373 $desc_map{$dkeys} = [@tmp];
v_mod6_genesis 374 }
v_mod6_genesis 375 }
v_mod6_genesis 376 }
v_mod6_genesis 377 remove_desc(sort keys %desc) if %desc;
v_mod6_genesis 378 }
v_mod6_genesis 379 }
v_mod6_genesis 380
v_mod6_genesis 381 sub get_all_descendant_nodes {
v_mod6_genesis 382 my (@vpatch) = @_;
v_mod6_genesis 383 my %desc = ();
v_mod6_genesis 384 foreach my $vp (@vpatch) {
v_mod6_genesis 385 %desc = descendants($vp);
v_mod6_genesis 386 if(keys %desc) {
v_mod6_genesis 387 my @dkeys = keys %desc;
v_mod6_genesis 388 $desc_map{$vp} = [@dkeys];
v_mod6_genesis 389 get_all_descendant_nodes(sort @dkeys);
v_mod6_genesis 390 }
v_mod6_genesis 391 if(!%desc) {
v_mod6_genesis 392 $desc_map{$vp} = [];
v_mod6_genesis 393 }
v_mod6_genesis 394 }
v_mod6_genesis 395 return %desc_map;
v_mod6_genesis 396 }
v_mod6_genesis 397
v_mod6_genesis 398 sub toposort {
v_mod6_genesis 399 my (%unsorted) = @_;
v_mod6_genesis 400 my $acyclic = "", my $flag = "f", my @flow = ();
v_mod6_genesis 401 while(%unsorted) {
v_mod6_genesis 402 $acyclic = "false";
v_mod6_genesis 403 foreach my $node (sort keys %unsorted) {
v_mod6_genesis 404 my @edges = @{$unsorted{$node}};
v_mod6_genesis 405 foreach my $edge (@edges) {
v_mod6_genesis 406 $flag = "t" and last if exists $unsorted{$edge};
v_mod6_genesis 407 }
v_mod6_genesis 408 if($flag ne "t") {
v_mod6_genesis 409 $acyclic = "true";
v_mod6_genesis 410 delete $unsorted{$node};
v_mod6_genesis 411 push @flow, $node;
v_mod6_genesis 412 }
v_mod6_genesis 413 $flag = "";
v_mod6_genesis 414 }
v_mod6_genesis 415 if(!$acyclic eq "true") {
v_mod6_genesis 416 death("Cyclic Graph!\n");
v_mod6_genesis 417 }
v_mod6_genesis 418 }
v_mod6_99993 419 return @flow;
v_mod6_genesis 420 }
v_mod6_genesis 421
v_mod6_genesis 422 sub press_vpatches {
v_mod6_genesis 423 my ($p, @flow) = @_;
v_mod6_genesis 424 my @press = @{$p};
v_mod6_genesis 425 my $v = 1 and shift @press if $press[0] =~ /^v$|^verbose$/i;
v_mod6_genesis 426 death("HEAD: $press[1] not found in flow\n") if !grep /^$press[1]$/, @flow;
v_mod6_99993 427 my @pp = calc_press_path($press[1]);
v_mod6_99993 428 death("Directory $press[0] already exists! Halting press.\n") if -d $press[0];
v_mod6_genesis 429 `mkdir -p $press[0]`;
v_mod6_99993 430 foreach my $vp (@pp) {
v_mod6_genesis 431 if($v) {
v_mod6_genesis 432 my @out = `patch -F 0 -E --dir $press[0] -p1 < $pdir/$vp 2>&1`;
v_mod6_genesis 433 print "$vp\n";
v_mod6_genesis 434 foreach my $o (@out) { print " $o"; }
v_mod6_genesis 435 } else {
v_mod6_genesis 436 `patch -F 0 -E --dir $press[0] -p1 < $pdir/$vp`;
v_mod6_genesis 437 }
v_mod6_genesis 438 %vp_map = ();
v_mod6_genesis 439 verify_pressed($press[0], add_pressed($vp));
v_mod6_genesis 440 last if $vp eq $press[1];
v_mod6_genesis 441 }
v_mod6_genesis 442 }
v_mod6_genesis 443
v_mod6_genesis 444 sub add_pressed {
v_mod6_genesis 445 my ($vpatch) = @_;
v_mod6_genesis 446 $vp_map{$vpatch} = $map{$vpatch};
v_mod6_genesis 447 return %vp_map;
v_mod6_genesis 448 }
v_mod6_genesis 449
v_mod6_genesis 450 sub get_filepath {
v_mod6_genesis 451 my ($fp) = @_;
v_mod6_genesis 452 $fp =~ /^[a|b]\/(.*)$/;
v_mod6_genesis 453 return $1;
v_mod6_genesis 454 }
v_mod6_genesis 455
v_mod6_genesis 456 sub verify_pressed {
v_mod6_genesis 457 my ($press_dir, %vp_map) = @_;
v_mod6_genesis 458 foreach my $vp (keys %vp_map) {
v_mod6_genesis 459 foreach my $src_file_name (keys %{$vp_map{$vp}}) {
v_mod6_genesis 460 my $file_hash = $vp_map{$vp}{$src_file_name}{b};
v_mod6_genesis 461 if($file_hash ne "false") {
v_mod6_genesis 462 my $fp = $press_dir . "/" . get_filepath($src_file_name);
v_mod6_genesis 463 my $hashed = `sha512sum $fp`;
v_mod6_genesis 464 $hashed =~ /^(.*) .*$/;
v_mod6_genesis 465 my $pressed_hash = $1;
v_mod6_genesis 466 if($file_hash ne $pressed_hash) {
v_mod6_genesis 467 print " File: $fp\n" .
v_mod6_genesis 468 "Expected: $file_hash\n" .
v_mod6_genesis 469 " Actual: $pressed_hash\n";
v_mod6_genesis 470 death("Pressed file hash did not match expected!\n");
v_mod6_genesis 471 }
v_mod6_genesis 472 }
v_mod6_genesis 473 }
v_mod6_genesis 474 }
v_mod6_genesis 475 }
v_mod6_genesis 476
v_mod6_genesis 477 sub sync_seals {
v_mod6_genesis 478 my ($URL, $out) = @_;
v_mod6_genesis 479 if(!-d $out) { `mkdir -p $out`; }
v_mod6_genesis 480 my $wget = "wget -q -r -nd -N --no-parent " .
v_mod6_genesis 481 "--reject \"index.html*\" $URL/v/seals/ -P $out";
v_mod6_genesis 482 `$wget`;
v_mod6_genesis 483 print "Seal sync complete to \"$out\"\n";
v_mod6_genesis 484 }
v_mod6_genesis 485
v_mod6_genesis 486 sub sync_vpatches {
v_mod6_genesis 487 my ($URL, $out, @sync) = @_;
v_mod6_genesis 488 my $wget = "";
v_mod6_genesis 489 if(!-d $out) { `mkdir -p $out`; }
v_mod6_genesis 490 foreach my $vpatch (@sync) {
v_mod6_genesis 491 $wget = "wget -q -r -nd -N --no-parent " .
v_mod6_genesis 492 "--reject \"index.html*\" $URL/v/patches/$vpatch -P $out";
v_mod6_genesis 493 `$wget`;
v_mod6_genesis 494 print "$vpatch sync complete to \"$out\"\n";
v_mod6_genesis 495 }
v_mod6_genesis 496 }
v_mod6_genesis 497
v_mod6_genesis 498 sub sync_all_vpatches {
v_mod6_genesis 499 my ($URL, $out) = @_;
v_mod6_genesis 500 if(!-d $out) { `mkdir -p $out`; }
v_mod6_genesis 501 my $wget = "wget -q -r -nd -N --no-parent " .
v_mod6_genesis 502 "--reject \"index.html*\" $URL/v/patches/ -P $out";
v_mod6_genesis 503 `$wget`;
v_mod6_genesis 504 print "Full vpatch sync complete to \"$out\"\n";
v_mod6_genesis 505 }
v_mod6_genesis 506
v_mod6_genesis 507 sub sync_everything {
v_mod6_genesis 508 my ($URL, $pd, $sd) = @_;
v_mod6_genesis 509 sync_all_vpatches($URL, $pd);
v_mod6_genesis 510 sync_seals($URL, $sd);
v_mod6_genesis 511 }
v_mod6_genesis 512
v_mod6_genesis 513 sub build_desc_full_graph {
v_mod6_genesis 514 $graph->set_attributes("graph",
v_mod6_genesis 515 {
v_mod6_genesis 516 font => "monospace",
v_mod6_genesis 517 label => "..::[ The Bitcoin Foundation: Vpatch Graph ]::.."
v_mod6_genesis 518 });
v_mod6_genesis 519 $graph->set_attributes("node",
v_mod6_genesis 520 {
v_mod6_genesis 521 linkbase => "http://thebitcoin.foundation/v/patches/",
v_mod6_genesis 522 autolink => "name",
v_mod6_genesis 523 color => "blue"
v_mod6_genesis 524 });
v_mod6_genesis 525 my @roots = roots();
v_mod6_genesis 526 foreach my $root (@roots) {
v_mod6_genesis 527 my $node = $graph->add_node($root);
v_mod6_genesis 528 $node->set_attribute("title", "Signed By: " . get_signatories($root));
v_mod6_genesis 529 my %desc = descendants($root);
v_mod6_genesis 530 my @dkeys = keys %desc;
v_mod6_genesis 531 add_desc_edges($root, @dkeys);
v_mod6_genesis 532 my @sn = $graph->source_nodes();
v_mod6_genesis 533 add_desc_src_files($sn[0]);
v_mod6_genesis 534 }
v_mod6_genesis 535 }
v_mod6_genesis 536
v_mod6_genesis 537 sub add_desc_edges {
v_mod6_genesis 538 my ($origin, @vpatch) = @_;
v_mod6_genesis 539 my %desc = ();
v_mod6_genesis 540 foreach my $vp (@vpatch) {
v_mod6_genesis 541 %desc = descendants($vp);
v_mod6_genesis 542 my $node = $graph->add_node($vp);
v_mod6_genesis 543 my $sigs = get_signatories($vp);
v_mod6_genesis 544 $node->set_attribute("title", "Signed By: $sigs");
v_mod6_genesis 545 $graph->add_edge_once($origin, $vp);
v_mod6_genesis 546 if(keys %desc) {
v_mod6_genesis 547 my @dkeys = sort keys %desc;
v_mod6_genesis 548 add_desc_edges($vp, @dkeys);
v_mod6_genesis 549 }
v_mod6_genesis 550 }
v_mod6_genesis 551 }
v_mod6_genesis 552
v_mod6_genesis 553 sub add_desc_src_files {
v_mod6_genesis 554 my ($node) = @_;
v_mod6_genesis 555 if($node != "") {
v_mod6_genesis 556 my %desc = descendants($node->name());
v_mod6_genesis 557 my @suc = $node->successors();
v_mod6_genesis 558 foreach my $s (@suc) {
v_mod6_genesis 559 my $name = $s->name();
v_mod6_genesis 560 my @edges = $node->edges_to($s);
v_mod6_genesis 561 foreach my $e (@edges) {
v_mod6_genesis 562 $e->set_attribute("title", "[ " .
v_mod6_genesis 563 join('; ', sort @{$desc{$name}}) . " ]");
v_mod6_genesis 564 add_desc_src_files($s);
v_mod6_genesis 565 }
v_mod6_genesis 566 }
v_mod6_genesis 567 }
v_mod6_genesis 568 }
v_mod6_genesis 569
v_mod6_genesis 570 sub rank_leafs_gviz {
v_mod6_genesis 571 build_desc_full_graph();
v_mod6_genesis 572 my $gviz = $graph->as_graphviz();
v_mod6_genesis 573 my @leafs = leafs();
v_mod6_genesis 574 $gviz =~ s/GRAPH_0/VPATCH_GRAPH/;
v_mod6_genesis 575 $gviz =~ s/rankdir=LR/rankdir=BT,ranksep=1.00,nodesep=.50/;
v_mod6_genesis 576 $gviz =~ s/}$//;
v_mod6_genesis 577 $gviz .= " { rank=same; ";
v_mod6_genesis 578 foreach my $l (@leafs) {
v_mod6_genesis 579 $gviz .= "\"$l\" ";
v_mod6_genesis 580 }
v_mod6_genesis 581 $gviz .= "}\n}";
v_mod6_genesis 582 return $gviz;
v_mod6_genesis 583 }
v_mod6_genesis 584
v_mod6_genesis 585 sub make_tmpdir {
v_mod6_99993 586 if(-d "/tmp") { $tdir = `mktemp -d`; } else { $tdir = `mktemp -d -p .`; }
v_mod6_99993 587 chomp($tdir);
v_mod6_99993 588 death("Failed to create tempdir!\n") if $tdir eq "";
v_mod6_genesis 589 }
v_mod6_genesis 590
v_mod6_genesis 591 sub death {
v_mod6_genesis 592 my ($msg) = @_;
v_mod6_genesis 593 remove_tmpdir($tdir);
v_mod6_genesis 594 die "$msg";
v_mod6_genesis 595 }
v_mod6_genesis 596
v_mod6_genesis 597 sub remove_tmpdir {
v_mod6_genesis 598 my ($dir) = @_;
v_mod6_genesis 599 `rm -rf $dir` if -d $dir;
v_mod6_genesis 600 }
v_mod6_genesis 601
v_mod6_genesis 602 sub print_graph {
v_mod6_genesis 603 my ($graph, @gv) = @_;
v_mod6_genesis 604 if(!@gv) {
v_mod6_genesis 605 print "$graph\n";
v_mod6_genesis 606 } elsif($#gv eq 1) {
v_mod6_genesis 607 open FH, ">$gv[0]"; print FH "$graph\n";
v_mod6_genesis 608 close FH;
v_mod6_genesis 609 print "Printed Graphviz dot file to $gv[0]\n";
v_mod6_genesis 610 my @which = `which dot`; chomp($which[0]);
v_mod6_genesis 611 if($which[0] =~ /dot/) {
v_mod6_genesis 612 `$which[0] -Tsvg $gv[0] > $gv[1]`;
v_mod6_genesis 613 } else {
v_mod6_genesis 614 print "`dot` binary not found, check if 'graphviz' is installed\n";
v_mod6_genesis 615 }
v_mod6_genesis 616 print "Executed `dot` and built svg html output file: $gv[1]\n";
v_mod6_genesis 617 } else {
v_mod6_genesis 618 open FH, ">$gv[0]"; print FH "$graph\n";
v_mod6_genesis 619 close FH;
v_mod6_genesis 620 print "Printed Graphviz dot file to $gv[0]\n";
v_mod6_genesis 621 }
v_mod6_genesis 622 }
v_mod6_genesis 623
v_mod6_genesis 624 sub get_mirrors {
v_mod6_genesis 625 my ($out) = @_;
v_mod6_genesis 626 my @mirror_sigs = ();
v_mod6_genesis 627 if(!-d $out) { `mkdir -p $out`; }
v_mod6_genesis 628 my $wget = "wget -q -r -nd -N --no-parent " .
v_mod6_genesis 629 "--reject \"index.html*\" -A 'mirrors.*' " .
v_mod6_genesis 630 "http://thebitcoin.foundation/v/ -P $out";
v_mod6_genesis 631 `$wget`;
v_mod6_genesis 632
v_mod6_genesis 633 my @sigs = `ls $out | sort`;
v_mod6_genesis 634 @sigs = wash(@sigs);
v_mod6_genesis 635 foreach my $sig (@sigs) {
v_mod6_genesis 636 my $who = $1 if $sig =~ /.*\..*\.(.*)\..*/;
v_mod6_genesis 637 my $verify = "gpg --homedir $tdir --logger-fd 1 --verify $out/$sig " .
v_mod6_genesis 638 "$out/mirrors.txt";
v_mod6_genesis 639 my @res = `$verify`;
v_mod6_genesis 640 foreach my $r (@res) {
v_mod6_genesis 641 if($r =~ /Good signature/) {
v_mod6_genesis 642 push @mirror_sigs, $who;
v_mod6_genesis 643 next;
v_mod6_genesis 644 }
v_mod6_genesis 645 }
v_mod6_genesis 646 }
v_mod6_genesis 647 return @mirror_sigs;
v_mod6_genesis 648 }
v_mod6_genesis 649
v_mod6_genesis 650 sub print_mirrors {
v_mod6_genesis 651 my ($out) = @_;
v_mod6_genesis 652 my @mirror_sigs = get_mirrors($out);
v_mod6_genesis 653
v_mod6_genesis 654 if(-d $out) {
v_mod6_genesis 655 my @mirrors = `cat $out/mirrors.txt`;
v_mod6_genesis 656 print "Mirrors signed by (" . join(', ', sort @mirror_sigs) . "):\n";
v_mod6_genesis 657 foreach(@mirrors) { chomp($_); print "$_\n"; }
v_mod6_genesis 658 }
v_mod6_genesis 659 }
v_mod6_genesis 660
v_mod6_genesis 661 sub print_roots {
v_mod6_genesis 662 my @r = roots();
v_mod6_genesis 663 foreach(@r) {
v_mod6_genesis 664 print "Root: $_ " . get_signatories($_) . "\n";
v_mod6_genesis 665 }
v_mod6_genesis 666 }
v_mod6_genesis 667
v_mod6_genesis 668 sub print_leafs {
v_mod6_genesis 669 my @l = leafs();
v_mod6_genesis 670 foreach(@l) {
v_mod6_genesis 671 print "Leaf: $_ " . get_signatories($_) . "\n";
v_mod6_genesis 672 }
v_mod6_genesis 673 }
v_mod6_genesis 674
v_mod6_genesis 675 sub print_wot {
v_mod6_genesis 676 my ($finger) = @_;
v_mod6_genesis 677 if(%wot) {
v_mod6_genesis 678 foreach my $uid (sort keys %wot) {
v_mod6_genesis 679 if(!$finger) {
v_mod6_genesis 680 print "$uid:$wot{$uid}{fp}:$wot{$uid}{banner}\n";
v_mod6_genesis 681 } else {
v_mod6_genesis 682 print "$uid-" . substr($wot{$uid}{fp}, -16) .
v_mod6_genesis 683 ":$wot{$uid}{fp}:$wot{$uid}{banner}\n";
v_mod6_genesis 684 }
v_mod6_genesis 685 }
v_mod6_genesis 686 }
v_mod6_genesis 687 }
v_mod6_genesis 688
v_mod6_genesis 689 sub print_antecedents {
v_mod6_genesis 690 my ($vpatch) = @_;
v_mod6_genesis 691 my %ante = antecedents($vpatch);
v_mod6_genesis 692 my $sigs;
v_mod6_genesis 693 foreach my $a (sort keys %ante) {
v_mod6_genesis 694 $sigs = get_signatories($a);
v_mod6_genesis 695 print "Antecedent: $a $sigs [ " . join('; ', sort @{$ante{$a}}) . " ]\n";
v_mod6_genesis 696 }
v_mod6_genesis 697 }
v_mod6_genesis 698
v_mod6_genesis 699 sub print_descendants {
v_mod6_genesis 700 my ($vpatch) = @_;
v_mod6_genesis 701 my %desc = descendants($vpatch);
v_mod6_genesis 702 my $sigs;
v_mod6_genesis 703 foreach my $d (sort keys %desc) {
v_mod6_genesis 704 $sigs = get_signatories($d);
v_mod6_genesis 705 print "Descendant: $d $sigs [ " . join('; ', sort @{$desc{$d}}) . " ]\n";
v_mod6_genesis 706 }
v_mod6_genesis 707 }
v_mod6_genesis 708
v_mod6_genesis 709 sub print_origin {
v_mod6_genesis 710 my ($hash) = @_;
v_mod6_genesis 711 my $found = "f";
v_mod6_genesis 712 foreach my $k (keys %map) {
v_mod6_genesis 713 foreach my $sf (keys %{$map{$k}}) {
v_mod6_genesis 714 if($map{$k}{$sf}{b} eq $hash) {
v_mod6_genesis 715 $found = "t";
v_mod6_genesis 716 print "Origin: $k " . get_signatories($k) . "\n";
v_mod6_genesis 717 }
v_mod6_genesis 718 }
v_mod6_genesis 719 }
v_mod6_genesis 720 print "No Origin Found by Hash: $hash\n" if $found ne "t";
v_mod6_genesis 721 }
v_mod6_genesis 722
v_mod6_genesis 723 sub print_flow {
v_mod6_genesis 724 my (@flow) = @_;
v_mod6_genesis 725 foreach(@flow) { print "$_ " . get_signatories($_) . "\n"; }
v_mod6_genesis 726 }
v_mod6_genesis 727
v_mod6_99993 728 sub print_press_path {
v_mod6_99993 729 my ($head) = @_;
v_mod6_99993 730 my @pp = calc_press_path($head);
v_mod6_99993 731 foreach(@pp) { print "$_ " . get_signatories($_) . "\n"; }
v_mod6_99993 732 }
v_mod6_99993 733
v_mod6_genesis 734 sub get_version {
v_mod6_genesis 735 my $version_text = << "END_VERSION_TEXT";
v_mod6_genesis 736 ################################################################################
v_mod6_genesis 737 # ..::[ The Bitcoin Foundation: V ]::.. #
v_mod6_genesis 738 # #
v_mod6_genesis 739 # Version: $version #
v_mod6_genesis 740 # Author: mod6 #
v_mod6_genesis 741 # Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF #
v_mod6_genesis 742 # #
v_mod6_genesis 743 ################################################################################
v_mod6_genesis 744 END_VERSION_TEXT
v_mod6_genesis 745 return $version_text;
v_mod6_genesis 746 }
v_mod6_genesis 747
v_mod6_genesis 748 sub short_help {
v_mod6_genesis 749 my ($flag) = @_;
v_mod6_genesis 750 my $short_help = << "END_SHORT_HELP";
v_mod6_genesis 751 ################################################################################
v_mod6_genesis 752 # ..::[ The Bitcoin Foundation: V ]::.. #
v_mod6_genesis 753 # #
v_mod6_genesis 754 # Version: $version #
v_mod6_genesis 755 # Author: mod6 #
v_mod6_genesis 756 # Fingerprint: 0x027A8D7C0FB8A16643720F40721705A8B71EADAF #
v_mod6_genesis 757 # #
v_mod6_genesis 758 # Usage: v.pl #
v_mod6_genesis 759 # (m | mirrors) (<output_dir>) #
v_mod6_genesis 760 # (i | init) (mirror_url) [(<pdir> <sdir>)] #
v_mod6_genesis 761 # (wd | wotdir) (<wotdir>) #
v_mod6_genesis 762 # (pd | patchdir) (<patchdir>) #
v_mod6_genesis 763 # (sd | sealdir) (<sealdir>) #
v_mod6_genesis 764 # (w | wot) [ finger ] #
v_mod6_genesis 765 # (r | roots) #
v_mod6_genesis 766 # (l | leafs) #
v_mod6_genesis 767 # (f | flow) #
v_mod6_genesis 768 # (p | press) (<press_dir> <head>) #
v_mod6_99993 769 # (pp | press-path) (<head>) #
v_mod6_genesis 770 # (ss | sync-seals) (<mirror_url> <sdir>) #
v_mod6_genesis 771 # (sv | sync-vpatches) (<mirror_url> <pdir> <vpatches>... ) #
v_mod6_genesis 772 # (sa | sync-all-vpatches) (<mirror_url> <pdir>) #
v_mod6_genesis 773 # (se | sync-everything) (<mirror_url> <pdir> <sdir>) #
v_mod6_genesis 774 # (a | ante | antecedents) (<vpatch>) #
v_mod6_genesis 775 # (d | desc | descendants) (<vpatch>) #
v_mod6_genesis 776 # (o | origin) (<sha512_hash>) #
v_mod6_genesis 777 # (g | graph) (<output_dotfile> [<output_svg_html_file>]) #
v_mod6_genesis 778 # (v | version) #
v_mod6_99993 779 # (h | help) #
v_mod6_genesis 780 # #
v_mod6_genesis 781 END_SHORT_HELP
v_mod6_genesis 782 my $l = "########################################" .
v_mod6_genesis 783 "########################################\n";
v_mod6_genesis 784 if($flag) { $short_help .= $l; }
v_mod6_genesis 785 return $short_help;
v_mod6_genesis 786 }
v_mod6_genesis 787
v_mod6_genesis 788 sub long_help {
v_mod6_genesis 789 print short_help();
v_mod6_genesis 790 my $long_help = << "END_LONG_HELP";
v_mod6_genesis 791 # Commands: #
v_mod6_genesis 792 # m, mirrors (<output_dir>) #
v_mod6_genesis 793 # Will attempt to retrieve, cryptographically verify and print entries #
v_mod6_99993 794 # in this list for usage in other commands. Mirrors command may only #
v_mod6_99993 795 # be invoked by itself. [See: sync-seals, sync-vpatches, #
v_mod6_99993 796 # sync-everything] #
v_mod6_genesis 797 # #
v_mod6_genesis 798 # i, init (<mirror_url>) [(<pdir> <sdir>)] #
v_mod6_genesis 799 # init should be run as the first command executed with V. init only #
v_mod6_genesis 800 # requires one option: <mirror_url>. The <pdir> and <sdir> options are #
v_mod6_genesis 801 # optional. Use these if you want to override the default Vpatches and #
v_mod6_genesis 802 # Seals directories in that exact order. #
v_mod6_genesis 803 # #
v_mod6_genesis 804 # Defaults: "~/.wot", "patches" (in present working directory) and #
v_mod6_genesis 805 # "~/.seals" will be used as defaults. WoTs pubkeys can not be sync'd #
v_mod6_genesis 806 # these need to be placed in the WoT directory manually. #
v_mod6_genesis 807 # #
v_mod6_genesis 808 # Set <mirror_url> to one of the signed URLs in the PGP signed mirrors #
v_mod6_genesis 809 # list at: http://thebitcoin.foundation/v/mirrors.txt #
v_mod6_genesis 810 # #
v_mod6_genesis 811 # wd, wotdir (<wotdir>) #
v_mod6_genesis 812 # Given the required option <wotdir>, overrides the default wotdir #
v_mod6_genesis 813 # ( .wot in the current working directory ) containing PGP public keys. #
v_mod6_genesis 814 # #
v_mod6_genesis 815 # pd, patchdir (<patchdir>) #
v_mod6_genesis 816 # Given required option of <patchdir>, overrides the default #
v_mod6_genesis 817 # patchdir ( ./patches ) containing vpatch files. #
v_mod6_genesis 818 # #
v_mod6_genesis 819 # sd, sealdir (<sealdir>) #
v_mod6_genesis 820 # Given required option of <sealdir>, overrides the default sealdir #
v_mod6_genesis 821 # ( .seals in the current working directory ) containing PGP detached #
v_mod6_genesis 822 # signatures of vpatch files. #
v_mod6_genesis 823 # #
v_mod6_genesis 824 # w, wot [ finger ] #
v_mod6_genesis 825 # Loads PGP public keys from wotdir and prints the WoT to stdout #
v_mod6_genesis 826 # #
v_mod6_genesis 827 # r, roots #
v_mod6_genesis 828 # Finds the root vpatches (which have no antecedents) and prints them #
v_mod6_genesis 829 # to stdout. #
v_mod6_genesis 830 # #
v_mod6_genesis 831 # l, leafs #
v_mod6_genesis 832 # Finds the leaf vpatches (which have no descendants) and prints them #
v_mod6_genesis 833 # to stdout. #
v_mod6_genesis 834 # #
v_mod6_genesis 835 # f, flow #
v_mod6_genesis 836 # Prints the topological flow of vpatches based on precedence. #
v_mod6_genesis 837 # #
v_mod6_genesis 838 # p, press (<press_dir> <head>) #
v_mod6_genesis 839 # Given required options <press_dir> output directory and <vpatch> #
v_mod6_genesis 840 # press will apply vpatches in topologicial order up through the #
v_mod6_genesis 841 # supplied (head) vpatch. Will print patching output if 'verbose' flag #
v_mod6_genesis 842 # is supplied immediately after ( p | press ) option. #
v_mod6_genesis 843 # See: ( f | flow ) to view the topological ordering. #
v_mod6_genesis 844 # #
v_mod6_99993 845 # pp, press-path (<head>) #
v_mod6_99993 846 # Print the actual path to be pressed, given a <head> found in the #
v_mod6_99993 847 # flow. #
v_mod6_99993 848 # #
v_mod6_genesis 849 # ss, sync-seals (<mirror_url> <sdir>) #
v_mod6_genesis 850 # Given required options of <mirror_url> and output directory <sdir> #
v_mod6_genesis 851 # will pull all of the available seal files from the given mirror into #
v_mod6_genesis 852 # output directory. #
v_mod6_genesis 853 # #
v_mod6_genesis 854 # sv, sync-vpatches (<mirror_url> <pdir> <vpatch>... ) #
v_mod6_genesis 855 # Given required options of <mirror_url> and output directory <pdir> #
v_mod6_genesis 856 # will pull the requested vpatch(s) from the given mirror into output #
v_mod6_genesis 857 # directory. #
v_mod6_genesis 858 # #
v_mod6_genesis 859 # sa, sync-all-vpatches (<mirror_url> <pdir>) #
v_mod6_genesis 860 # Given required options of <mirror_url> and output directory <pdir> #
v_mod6_genesis 861 # will pull all available vpatches from the given mirror into output #
v_mod6_genesis 862 # directory. #
v_mod6_genesis 863 # #
v_mod6_genesis 864 # se, sync-everything (<mirror_url> <pdir> <sdir>) #
v_mod6_genesis 865 # Given required options of <mirror_url>, <pdir>, and <sdir>; #
v_mod6_genesis 866 # sync-everything will pull all of the available seals and vpatches #
v_mod6_genesis 867 # available at the given mirror. #
v_mod6_genesis 868 # #
v_mod6_genesis 869 # a, ante, antecedents (<vpatch>) #
v_mod6_genesis 870 # Finds the antecedents of a given vpatch and prints the results to #
v_mod6_genesis 871 # stdout #
v_mod6_genesis 872 # #
v_mod6_genesis 873 # d, desc, descendants (<vpatch>) #
v_mod6_genesis 874 # Finds the descendants of a given vpatch and prints the results to #
v_mod6_genesis 875 # stdout #
v_mod6_genesis 876 # #
v_mod6_genesis 877 # o, origin (<sha512_hash>) #
v_mod6_genesis 878 # Returns the vpatch and signatories where the given hash originated in #
v_mod6_genesis 879 # the source tree. #
v_mod6_genesis 880 # #
v_mod6_genesis 881 # g, graph (<output_dotfile> [<output_svg_html_file>]) #
v_mod6_genesis 882 # Builds a complete directed GraphViz graph of all vpatches from a #
v_mod6_genesis 883 # topological flow and prints the Dot language output to file. If the #
v_mod6_genesis 884 # output_svg_html_file argument is supplied the V will attempt to parse #
v_mod6_genesis 885 # the output_dotfile into an html file; Requires having separately #
v_mod6_genesis 886 # installed 'graphviz' ahead of time. #
v_mod6_genesis 887 # #
v_mod6_genesis 888 # v, version #
v_mod6_genesis 889 # Prints the version message. #
v_mod6_genesis 890 # #
v_mod6_99993 891 # h, help #
v_mod6_genesis 892 # Prints this full help message. #
v_mod6_genesis 893 # #
v_mod6_genesis 894 ################################################################################
v_mod6_genesis 895 END_LONG_HELP
v_mod6_genesis 896 return $long_help;
v_mod6_genesis 897 }
v_mod6_genesis 898
v_mod6_genesis 899 sub main {
v_mod6_99993 900 check_required_bins(@dep_bins);
v_mod6_99993 901
v_mod6_genesis 902 my $cmd;
v_mod6_genesis 903 if(@ARGV > 0) { $cmd = shift @ARGV; }
v_mod6_genesis 904 else { print "Unknown or missing option!\n"; print short_help("t"); return; }
v_mod6_genesis 905
v_mod6_genesis 906 my $pwd = get_pwd();
v_mod6_genesis 907 $wdir = "$pwd/.wot";
v_mod6_genesis 908 $pdir = "$pwd/patches";
v_mod6_genesis 909 $sdir = "$pwd/.seals";
v_mod6_genesis 910
v_mod6_genesis 911 if(($cmd =~ /^m$|^mirrors$/i ||
v_mod6_genesis 912 $cmd =~ /^i$|^init$/i ||
v_mod6_genesis 913 $cmd =~ /^wd$|^wotdir$/i ||
v_mod6_genesis 914 $cmd =~ /^pd$|^patchdir$/i ||
v_mod6_genesis 915 $cmd =~ /^sd$|^sealdir$/i ||
v_mod6_genesis 916 $cmd =~ /^p$|^press$/i ||
v_mod6_genesis 917 $cmd =~ /^ss$|^sync-seals$/i ||
v_mod6_genesis 918 $cmd =~ /^sv$|^sync-vpatches$/i ||
v_mod6_genesis 919 $cmd =~ /^sa$|^sync-all-vpatches$/i ||
v_mod6_genesis 920 $cmd =~ /^sa$|^sync-all-vpatches$/i ||
v_mod6_genesis 921 $cmd =~ /^se$|^sync-everything$/i ||
v_mod6_genesis 922 $cmd =~ /^a$|^ante$|^antecedents$/i ||
v_mod6_genesis 923 $cmd =~ /^d$|^desc$|^descendants$/i ||
v_mod6_genesis 924 $cmd =~ /^o$|^origin$/i ||
v_mod6_genesis 925 $cmd =~ /^g$|^graph$/i) && !@ARGV) {
v_mod6_genesis 926 print "Option \"$cmd\" requires arguments!\n";
v_mod6_genesis 927 print short_help("t"); return;
v_mod6_genesis 928 }
v_mod6_genesis 929
v_mod6_genesis 930 my @tmp = ();
v_mod6_genesis 931 while(@ARGV > 0) {
v_mod6_genesis 932 if($ARGV[0] =~ /^wd$|^wotdir$/) {
v_mod6_genesis 933 shift @ARGV; $wdir = shift @ARGV; next;
v_mod6_genesis 934 } elsif($ARGV[0] =~ /^pd$|^patchdir$/) {
v_mod6_genesis 935 shift @ARGV; $pdir = shift @ARGV; next;
v_mod6_genesis 936 } elsif($ARGV[0] =~ /^sd$|^sealdir$/) {
v_mod6_genesis 937 shift @ARGV; $sdir = shift @ARGV; next;
v_mod6_genesis 938 } else {
v_mod6_genesis 939 push @tmp, shift @ARGV;
v_mod6_genesis 940 }
v_mod6_genesis 941 }
v_mod6_genesis 942 @ARGV = @tmp;
v_mod6_genesis 943
v_mod6_genesis 944 @wfiles = set_files($wdir);
v_mod6_genesis 945 build_wot();
v_mod6_genesis 946
v_mod6_99993 947 if($cmd =~ /^h$|^help$/) { print long_help(); return; }
v_mod6_genesis 948 if($cmd =~ /^i$|^init$/) {
v_mod6_genesis 949 if(@ARGV == 1) {
v_mod6_genesis 950 init(@ARGV, $pdir, $sdir); return;
v_mod6_genesis 951 } elsif(@ARGV == 3) {
v_mod6_genesis 952 $sdir = pop @ARGV; $pdir = pop @ARGV;
v_mod6_genesis 953 init(@ARGV, $pdir, $sdir); return;
v_mod6_genesis 954 } else {
v_mod6_genesis 955 print "Incorrect number of arguments passed to init!\n";
v_mod6_genesis 956 print short_help("t"); return;
v_mod6_genesis 957 }
v_mod6_genesis 958 }
v_mod6_genesis 959
v_mod6_genesis 960 if($cmd =~ /^m$|^mirrors$/) { print_mirrors(@ARGV); return; }
v_mod6_genesis 961 if($cmd =~ /^w$|^wot$/) { print_wot(@ARGV); return; }
v_mod6_genesis 962 if($cmd =~ /^v$|^version$/) { print get_version(); return; }
v_mod6_genesis 963
v_mod6_genesis 964 @pfiles = set_files($pdir);
v_mod6_genesis 965 @sfiles = set_files($sdir);
v_mod6_genesis 966
v_mod6_genesis 967 validate_seals();
v_mod6_genesis 968 build_map();
v_mod6_genesis 969 my @flow = build_flow();
v_mod6_genesis 970
v_mod6_genesis 971 if ($cmd =~ /^r$|^roots$/) { print_roots(); }
v_mod6_genesis 972 elsif($cmd =~ /^l$|^leafs$/) { print_leafs(); }
v_mod6_genesis 973 elsif($cmd =~ /^f$|^flow$/) { print_flow(@flow); }
v_mod6_99993 974 elsif($cmd =~ /^pp$|^press-path$/) { print_press_path(@ARGV); }
v_mod6_genesis 975 elsif($cmd =~ /^p$|^press$/) {
v_mod6_genesis 976 if(@ARGV < 2) {
v_mod6_genesis 977 print "$cmd requires two arguments: (<press_dir> <head>)\n\n";
v_mod6_genesis 978 print short_help("t"); }
v_mod6_genesis 979 else { press_vpatches(\@ARGV, @flow); } }
v_mod6_genesis 980 elsif($cmd =~ /^ss$|^sync-seals$/) {
v_mod6_genesis 981 if(@ARGV < 2) {
v_mod6_genesis 982 print "$cmd requires two arguments: (<mirror_url> <sdir>)\n\n";
v_mod6_genesis 983 print short_help("t"); }
v_mod6_genesis 984 else { sync_seals(@ARGV); } }
v_mod6_genesis 985 elsif($cmd =~ /^sv$|^sync-vpatches$/) {
v_mod6_genesis 986 if(@ARGV < 3) {
v_mod6_genesis 987 print "$cmd requires three arguments: " .
v_mod6_genesis 988 "(<mirror_url> <pdir> <vpatch>... )\n\n"; print short_help("t"); }
v_mod6_genesis 989 else { sync_vpatches(@ARGV); } }
v_mod6_genesis 990 elsif($cmd =~ /^sa$|^sync-all-vpatches$/) {
v_mod6_genesis 991 if(@ARGV < 2) {
v_mod6_genesis 992 print "$cmd requires two arguments: " .
v_mod6_genesis 993 "(<mirror_url> <pdir>)\n\n"; print short_help("t"); }
v_mod6_genesis 994 else { sync_all_vpatches(@ARGV); } }
v_mod6_genesis 995 elsif($cmd =~ /^se$|^sync-everything$/) {
v_mod6_genesis 996 if(@ARGV < 3) {
v_mod6_genesis 997 print "$cmd requires three arguments: " .
v_mod6_genesis 998 "(<mirror_url> <pdir> <sdir>)\n\n"; print short_help("t"); }
v_mod6_genesis 999 else { sync_everything(@ARGV); } }
v_mod6_genesis 1000 elsif($cmd =~ /^a$|^ante$|^antecedents$/) { print_antecedents(@ARGV); }
v_mod6_genesis 1001 elsif($cmd =~ /^d$|^desc$|^descendants$/) { print_descendants(@ARGV); }
v_mod6_genesis 1002 elsif($cmd =~ /^o$|^origin$/) { print_origin(@ARGV); }
v_mod6_genesis 1003 elsif($cmd =~ /^g$|^graph$/) {
v_mod6_genesis 1004 my $mod = "Graph::Easy";
v_mod6_genesis 1005 (my $req = $mod . ".pm") =~ s{::}{/}g;
v_mod6_genesis 1006 require $req;
v_mod6_genesis 1007 $graph = $mod->new();
v_mod6_genesis 1008 print_graph(rank_leafs_gviz(), @ARGV); }
v_mod6_genesis 1009 else { print "Unknown option: \"$cmd\"\n"; print short_help("t"); }
v_mod6_genesis 1010 }
v_mod6_genesis 1011
v_mod6_99993 1012 make_tmpdir();
v_mod6_genesis 1013 main();
v_mod6_genesis 1014 remove_tmpdir($tdir);