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