(file) Return to LogSharedWriteChange.txt CVS log (file) (dir) Up to [OMI] / omi / base

   1 krisbash 1.1 @rem --*-Perl-*--
   2              @if "%overbose%" == "" if "%_echo%"=="" echo off
   3              setlocal
   4              for %%i in (oenvtest.bat) do call %%~$PATH:i
   5              perl.exe -x "%~dpnx0" %*
   6              goto :eof
   7              
   8              #!perl
   9              
  10              BEGIN {
  11                  # augment library path for OTOOLS environment
  12                  if (defined $ENV{"OTOOLS"}) {
  13                      require "$ENV{'OTOOLS'}\\lib\\perl\\otools.pm"; import otools;
  14                  }
  15              
  16                  # Convert "use strict 'subs'" to the eval below so we don't
  17                  # break if the user's @INC is set up wrong.  You'd be surprised
  18                  # how often this happens.
  19                  eval { require strict; import strict 'subs' };
  20              }
  21              
  22 krisbash 1.1 require 5.004;
  23              die "Unsupported OS ($^O), sorry.\n" if $^O eq "dos";
  24              
  25              sub Usage {
  26                  my $usage = <<'EOM';
  27              NAME
  28              
  29              $name - unpack a buddy build package
  30              
  31              SYNOPSIS
  32              
  33                  $name -?
  34              
  35                  $name [-A dir] [-B dir] [-d] [-c changelist] [-f] [-l] [-m from to] [-n]
  36                        [-R resolve-options] [-s] [-u] [-v] [-w] [-x]
  37              
  38              DESCRIPTION
  39              
  40                  Unpack the buddy build generated by a previous $pack.
  41              
  42              OPTIONS
  43 krisbash 1.1 
  44                  -?
  45              
  46                      Displays this help file.
  47              
  48                  -A dir
  49              
  50                      Directory to use for "after" files.  The directory will remain.
  51                      Must be used in conjunction with -w.
  52              
  53                  -B dir
  54              
  55                      Directory to use for "before" files.  The directory will remain.
  56                      Must be used in conjunction with -w.
  57              
  58                  -d
  59              
  60                      Turns on debugging spew.
  61              
  62                  -c changelist
  63              
  64 krisbash 1.1         Unpack the package onto the given changelist.  If this option
  65                      is omitted, the default changelist will be used.
  66              
  67                  -f
  68              
  69                      Unpack even if the changelist is nonempty.
  70              
  71                  -l
  72              
  73                      List contents of package.
  74              
  75                  -m from to
  76              
  77                      Unpack (merge) the package into a location possibly different
  78                      from the one it was built from.  "from" and "to" indicate the
  79                      relationship between the source and target depots.  For example,
  80                      if the original package was built from //depot/branch1/... and
  81                      you want to unpack to //depot/branch2/... you would specify
  82              
  83                          -m //depot/branch1/ //depot/branch2/
  84              
  85 krisbash 1.1         Note the trailing slashes.  The remapping is a purely textual
  86                      one:  All paths in the package that begin with "from" are
  87                      rewritten to begin with "to", hence the importance of the trailing
  88                      slash to avoid false matches.  If you misspell "from" or "to",
  89                      you are likely to get very strange results.
  90              
  91                      The files are unpacked into the current client, which
  92                      need not be enlisted onto the same server that the package
  93                      was generated from.
  94              
  95                      It is legal for "from" and "to" to be the same path.  This
  96                      results in merging a delta without moving it.  See the -M
  97                      option below.
  98              
  99                      May not be combined with the -s or -w switches.
 100              
 101                  -M
 102              
 103                      Shorthand for "-m // //", which merges a changelist without
 104                      moving it.
 105              
 106 krisbash 1.1     -n
 107              
 108                      Display what would have happened without actually doing
 109                      it.
 110              
 111                  -R  resolve-options
 112              
 113                      Arbitrary options to pass to "sd resolve3".  For example,
 114                      you could say
 115              
 116                          -R -af
 117              
 118                      to force automatic mode.  For a list of supported options,
 119                      type
 120              
 121                          sd help resolve3
 122              
 123                  -s
 124              
 125                      Synchronize to the versions of the files that are
 126                      the bases for the changes contained in the package,
 127 krisbash 1.1         but do not unpack them.
 128              
 129                      This is a convenient step to perform separately
 130                      from unpacking because it allows you to perform a
 131                      pre-build to ensure that the build was not broken
 132                      before you unpacked the files in the package.
 133              
 134                  -u
 135              
 136                      Perform the unpack.  This switch can be combined with
 137                      the -s switch to synchronize and unpack in one step.
 138              
 139                      The unpack will fail if the changelist is nonempty.
 140                      Use the "sd change" command to move files in the default
 141                      changelist to a new changelist.  This allows you to use
 142                      "sd revert -c default ..." to undo the unpack.
 143              
 144                      To force the unpack even if the changelist is empty,
 145                      pass the -f flag.  Note that doing so will result in the
 146                      unpacked files being added to your changelist,
 147                      which in turn makes reverting the unpack a much more
 148 krisbash 1.1         cumbersome operation.
 149              
 150                  -v
 151              
 152                      Verify that the package will produce results
 153                      identical to what's on the machine right now.
 154                      Use this immediately after generating a package as a
 155                      double-check.
 156              
 157                  -w
 158              
 159                      View contents of packages using windiff (or whatever your
 160                      BBDIFF environment variable refers to).
 161              
 162                  -x
 163              
 164                      Unpack the files as UNIX-style (LF only) rather than
 165                      Win32-style (CRLF).
 166              
 167                  -T
 168              
 169 krisbash 1.1         Preserve the last changed timestamps for all files when
 170                      unpacking.
 171              
 172              WARNINGS
 173              
 174                  warning: filename merge cancelled by user; skipped
 175              
 176                      A file in the package needed to be merged, but you abandoned
 177                      the merge operation ("s" or "q").  The file was left in its original
 178                      state; the changes were not merged in.
 179              
 180                  warning: //depot/.../filename not affected by branch mapping; skipped
 181              
 182                      The indicated file in the package is not affected by the
 183                      from/to mapping, so it was omitted from the merge.
 184              
 185              ERRORS
 186              
 187                  error: sd failed; unpack abandoned
 188              
 189                      One of the sd commands necessary to complete the unpack failed.
 190 krisbash 1.1         The sd error message should have been displayed immediately
 191                      before this message.
 192              
 193                  error: cannot find local copy of //depot/.../filename
 194              
 195                      The indicated file in the package could not be found on your
 196                      enlistment.  Perhaps you have not included it in your view.
 197              
 198                  internal error: cannot parse output of 'sd have'
 199                  internal error: Cannot parse output of 'sd opened'
 200              
 201                      There was a problem parsing the output of an sd command.
 202              
 203                  error: changelist is not empty; use -f -u to unpack anyway
 204              
 205                      The changelist is not empty, so the unpack
 206                      was abandoned.  To force unpacking into a nonempty
 207                      changelist, use the -f switch.
 208              
 209                  error: filename is already open on client; to merge, use the -M option
 210              
 211 krisbash 1.1         The specified file is already open.  It must be submitted or
 212                      reverted before the package can be unpacked cleanly.
 213              
 214                      Alternatively, you can unpack in "merge" mode, which merges
 215                      the changes in the package with the version on your machine.
 216                      Note that this will DESTROY the version on your machine in the
 217                      process, so back it up (possibly with bbpack) if there's a chance
 218                      the merge will not go well.
 219              
 220                  error: adds in this package already exist on client
 221              
 222                      The package contains an "add" operation, but the file already
 223                      exists.  It must be ghosted or deleted before the package can
 224                      be unpacked.
 225              
 226                  error: files to be edited/deleted do not exist on client
 227              
 228                      The package contains an "edit" or "delete" operation, but the
 229                      file does not exist on the client.  Perhaps you have not
 230                      included it in your view.
 231              
 232 krisbash 1.1     error: wrong version of filename on client
 233              
 234                      The base version of the file in the package does not match the
 235                      base version on the client.  Use the -s option to synchronize
 236                      to the version in the package.
 237              
 238                  error: filename does not match copy in package
 239              
 240                      The verification process (-v) failed.
 241              
 242                  error: corrupted package
 243              
 244                      An internal consistency check on the package has failed.  Either
 245                      it has been corrupted, or there is a bug in the program.
 246              
 247                  error: cannot open filename for writing (reason)
 248              
 249                      The specified error occurred attempting to open the indicated
 250                      file for writing.
 251              
 252                  error: filename: errorstring
 253 krisbash 1.1 
 254                      The specified error occurred attempting to open the indicated
 255                      file.
 256              
 257                  error: no TEMP directory
 258              
 259                      Neither the environment variable TEMP nor TMP could be found.
 260              
 261                  error: Too many TEMP### directories
 262              
 263                      Unable to create a temporary directory for windiff because there
 264                      are too many already.  Normally, temporary directories are cleaned
 265                      up automatically when the script terminates, but if the script
 266                      terminates abnormally, temporary directories may be left behind
 267                      and need to be cleaned up manually.
 268              
 269                  //deport/path/to/file.cpp - must refer to client 'CLIENTNAME'
 270                  error: sd failed; unpack abandoned
 271              
 272                      This is an sd error message.  You spelled "depot" wrong ("deport")
 273                      in the -m command line arguments.  As a result, sd thinks you are
 274 krisbash 1.1         trying to merge with the file "file.cpp" on the enlistment named
 275                      "deport", and sd won't let you check out a file on another person's
 276                      enlistment.
 277              
 278              TIPS
 279              
 280                  Brain surgery
 281              
 282                  $name stores as much state as possible in the depot itself in order
 283                  to keep the package small.  If your server changes its name, you have
 284                  to perform brain surgery on the package.  Load it up into notepad
 285                  and look for the _!_END_!_ line.  A few lines after the _!_END_!_ will
 286                  be a
 287              
 288                      Source Server Address: oldserver:portnumber
 289              
 290                  Change the server address to refer to the new server and new port
 291                  number.
 292              
 293                  NOTE!  Use Notepad and not "My Favorite Editor" because who knows
 294                  what "My Favorite Editor" does to tabs and trailing spaces and
 295 krisbash 1.1     that sort of thing.
 296              
 297              REMARKS
 298              
 299                  4NT users need to type
 300              
 301                      perl -Sx $name.cmd
 302              
 303                  instead of just $name.
 304              
 305              ENVIRONMENT
 306              
 307                  BBDIFF
 308              
 309                      The name of the diff program to use.  If not defined, the
 310                      SDDIFF variable is used to obtain the name of the file difference
 311                      program.  If neither is defined, then "windiff" is used.
 312              
 313                  BBUNPACKDEFCMD
 314              
 315                      The default command to execute if no command line options are
 316 krisbash 1.1         specified.  If not defined, then an error message is displayed.
 317              
 318                      For example, you might set BBUNPACKDEFCMD=-w to make the default
 319                      action when running a package to be to view the contents via
 320                      windiff.
 321              
 322                  Since $name runs sd internally, all the SD environment variables
 323                  also apply.
 324              
 325              BUGS
 326              
 327                  Several error messages leak out when you unpack an sd add.
 328                  (This is happening while verifying that the file about to be
 329                  added hasn't already been added.)
 330              
 331                  If the package contains an "add" command and the file exists
 332                  on the client but is not under source control, the file is overwritten
 333                  without warning.
 334              
 335                  There are almost certainly other bugs in this script somewhere.
 336              
 337 krisbash 1.1 VERSION
 338              
 339                  The package was generated by version 109 of $pack.
 340              
 341              EOM
 342                  $usage =~ s/\$name/$main::name/g;
 343                  $usage =~ s/\$pack/$main::pack/g;
 344              
 345                  # prevent false positives when searching for the magic cookie
 346                  $usage =~ s/_!_/__/g;
 347                  print $usage;
 348              }
 349              
 350              sub dprint {
 351                  print STDERR "# ", @_, "\n" if $main::d;
 352              }
 353              
 354              #
 355              #   $action is optional prefix for printing.
 356              #   $sharp says whether or not revisions should be kept.
 357              #   $ary is a ref to an array of [ $file, $rev ].
 358 krisbash 1.1 #
 359              #   We always convert the depot paths to local paths for perf.
 360              #   (It works around a perf bug in older versions of sds.)
 361              #
 362              #   Returns a ref to an array of strings to pass to -x.
 363              
 364              sub sdarg {
 365                  my ($action, $sharp, $ary) = @_;
 366                  my @out = ();
 367                  my %files;
 368                  my $rc = "";
 369              
 370                  for my $file (@$ary) {
 371                      my $depot = $file->[0];
 372                      $files{lc $depot} = $file;
 373                      push(@out, "$depot\n");
 374                  }
 375              
 376                  # Now convert the results into a list of local paths.  Anything
 377                  # that succeeds, edit it in the %files.  Anything that fails to map
 378                  # gets left alone, and sd will generate the real error later.
 379 krisbash 1.1 
 380                  my $tempfile = CreateTempFile(@out);
 381                  my $curDepot = undef;
 382                  for my $line (`sd.exe -x $tempfile -s where -T _`) {
 383                      if ($line =~ m|^info:|) {
 384                          $curDepot = undef;
 385                      } elsif ($line =~ m|^info1: depotFile (.*)$|) {
 386                          $curDepot = $1;
 387                      } elsif ($line =~ m|^info1: path (.*)$|) {
 388                          my $curFile = $files{lc $curDepot};
 389                          if ($curFile) {
 390                              $curFile->[0] = $1;
 391                              dprint "$curDepot -> $1";
 392                          }
 393                          $curDepot = undef;
 394                      }
 395                  }
 396                  unlink $tempfile;
 397              
 398                  # Now rebuild the results based on the localized paths.
 399                  @out = ();
 400 krisbash 1.1     for $file (values %files) {
 401                      push(@out, $file->[0]);
 402                      push(@out, "#" . $file->[1]) if $sharp;
 403                      push(@out, "\n");
 404                  }
 405              
 406                  \@out;
 407              }
 408              
 409              #
 410              #   $action is a command ("sync#", "edit", "add" and "delete")
 411              #
 412              #   The revision number is stripped off the file specification
 413              #   unless the action itself ends in a # (namely, sync#).
 414              #
 415              #   $ary is a ref to an array of [ $file, $rev ].
 416              
 417              sub sdaction {
 418                  my ($action, $ary) = @_;
 419                  my $sharp = $action =~ s/#$//;
 420              
 421 krisbash 1.1     if ($#$ary >= 0) {
 422              
 423                      my $args = sdarg($action, $sharp, $ary);
 424              
 425                      unless ($main::n) {
 426                          my $error = 0;
 427                          my $tempfile = CreateTempFile(@$args);
 428                          if (open(SD, "sd -x $tempfile -s $action |"))
 429                          {
 430                              my $line;
 431                              while ($line = <SD>) {
 432                                  if ($line =~ /^(\S+): /) {
 433                                      $error = 1 if $1 eq 'error';
 434                                      print $' unless $1 eq 'exit';
 435                                  }
 436                              }
 437                              close(SD);
 438                          }
 439                          unlink $tempfile;
 440                          die "error: sd failed; unpack abandoned\n" if $error;
 441                      }
 442 krisbash 1.1     }
 443              }
 444              
 445              sub slurpfile {
 446                  my ($file, $type) = @_;
 447                  my @file;
 448                  if ($type =~ /binary|unicode/) {
 449                      open(B, $file) or die "error: cannot open $file for reading ($!)\n";
 450                      binmode(B);
 451                      local($/);
 452                      push(@file, <B>);
 453                      close(B);
 454                  } else {
 455                      open(I, $file) or die "error: cannot open $file for reading ($!)\n";
 456                      @file = <I>;
 457                      close(I);
 458                  }
 459                  @file;
 460              }
 461              
 462              sub spewfile {
 463 krisbash 1.1     my ($file, $ary, $type) = @_;
 464                  if (!open(O, ">$file")) {
 465                      # Maybe the parent directory hasn't been created yet
 466                      my $dir = $file;
 467                      $dir =~ s/\//\\/g;
 468                      if ($dir =~ s/[^\\\/]+$//) {
 469                          system "md \"$dir\"" unless -e $dir; # let cmd.exe do the hard work
 470                      }
 471                      open(O, ">$file") or die "error: cannot open $file for writing ($!)\n";
 472                  }
 473                  binmode(O) if $main::x || $type =~ /binary|unicode/;
 474                  print O @$ary;
 475                  close(O);
 476              }
 477              
 478              sub GetUniqueName {
 479                  my $name = shift;
 480                  $name =~ s,^[/\\]*,,;   # clean out leading slashes
 481                  $name = substr($name, length($main::CommonPrefix));
 482                  $name =~ s,^[/\\]*,,;   # clean out leading slashes again
 483              
 484 krisbash 1.1     if (defined($main::UniqueNames{lc $name}))
 485                  {
 486                      my $i = 1;
 487                      $i++ while $main::UniqueNames{lc "$name$i"};
 488                      $name .= $i;
 489                  }
 490                  $main::UniqueNames{lc $name} = 1;
 491                  $name;
 492              }
 493              
 494              sub CreateTempFile {
 495                  my $TEMP = $ENV{"TEMP"} || $ENV{"TMP"};
 496                  die "error: no TEMP directory" unless $TEMP;
 497                  $TEMP =~ s/\\$//;     # avoid the \\ problem
 498              
 499                  $tempfile = "$TEMP\\bbpack.$$";
 500                  open(T, ">$tempfile") || die "error: Cannot create $tempfile\n";
 501                  my $success = print T @_;
 502                  $success = close(T) && $success;
 503                  unlink $tempfile, die "error: writing $tempfile ($!)\n" unless $success;
 504                  $tempfile;
 505 krisbash 1.1 }
 506              
 507              sub Remap {
 508                  my $path = shift;
 509                  if ($path =~ m#^\Q$main::fromDepot\E#i) {
 510                      substr($path, $[, length($main::fromDepot)) = $main::toDepot;
 511                  }
 512                  $path;
 513              }
 514              
 515              #
 516              #   $depotpath, $rev is the file to be edited/added.
 517              #   $cmd is "edit" or "add" (indicates where basefile comes from)
 518              #
 519              
 520              sub ApplyEdit {
 521                  my ($depotpath, $rev, $cmd, $type, $atime, $mtime) = @_;
 522                  my $destpath = $depotpath;
 523                  my $destfile;
 524                  my $where, $file;
 525              
 526 krisbash 1.1     if ($main::w) {
 527                      $file = $depotpath; # for the purpose of GetUniqueName
 528                  } else {
 529                      $destpath = Remap($depotpath) if $main::m;
 530                      dprint "$depotpath -> $destpath" if $main::m;
 531                      local($/) = ""; # "sd where -T" uses paragraphs
 532                      foreach $line (`sd.exe where -T _ \"$destpath\" 2>&1`) {
 533                          undef $where, next if $line =~ m|^\.\.\. unmap|m;
 534                          $where = $1 if $line =~ m|^\.\.\. path (.+)|m;
 535                      }
 536                      die "error: cannot find local copy of $destpath\n" unless $where;
 537                      $destfile = $file = $where;
 538                  }
 539                  my @file;
 540                  my $bias = -1;  # perl uses zero-based arrays but diff uses 1-based line numbers
 541              
 542                  if ($cmd eq 'add') {
 543                      @file = ();
 544                      $file = $destfile if $main::m;
 545                  } elsif ($cmd eq 'edit') {
 546                      my $src = $file;
 547 krisbash 1.1         if ($main::v || $main::w || $main::m) {
 548                          dprint "sd$main::ExtraFlags print -q \"$depotpath#$rev\"";
 549                          $src = "sd$main::ExtraFlags print -q \"$depotpath#$rev\"|";
 550                      }
 551                      @file = slurpfile($src, $type);
 552                  } elsif ($cmd eq 'delete') {
 553                      if ($main::w) {
 554                          dprint "sd$main::ExtraFlags print -q \"$depotpath#$rev\"";
 555                          @file = slurpfile("sd$main::ExtraFlags print -q \"$depotpath#$rev\"|", $type);
 556                      } else {
 557                          @file = ();
 558                      }
 559                  }
 560              
 561                  my $unique;
 562                  if ($main::w || ($main::m && $cmd eq "edit")) { # Write the original, set up for new
 563                      $unique = GetUniqueName($file);
 564                      spewfile("$main::BeforeDir\\$unique", \@file, $type) unless $cmd eq 'add';
 565                      $file = "$main::AfterDir\\$unique";
 566                  }
 567              
 568 krisbash 1.1     if ($cmd ne 'delete') {
 569                      # now read from <DATA> and apply the edits.
 570                      if ($type =~ /binary|unicode/) {
 571                          local($/) = "";
 572                          @file = (unpack("u", scalar(<DATA>)));
 573                      } else {
 574                          while (($line = <DATA>) ne "q\n") {
 575                              if ($line =~ /^a(\d+) (\d+)/) {
 576                                  my @added = ();
 577                                  my $count = $2;
 578                                  while ($count--) {
 579                                      push(@added, scalar(<DATA>));
 580                                  }
 581                                  splice(@file, $1 + $bias + 1, 0, @added); # +1 because it's "add", not "insert"
 582                                  $bias += $2;
 583                              } elsif ($line =~ /^d(\d+) (\d+)/) {
 584                                  splice(@file, $1 + $bias, $2);
 585                                  $bias -= $2;
 586                              } else {
 587                                  die "error: corrupted package trying to unpack $depotpath\n".
 588                                      "       expected a/d/q but got\n".
 589 krisbash 1.1                         "           $line";
 590                              }
 591                          }
 592              
 593                          if ($type =~ /_nonewline/) {
 594                              chomp($file[$#file]);
 595                          }
 596                      }
 597              
 598                      if ($main::v) {
 599                          my @file2 = slurpfile($file, $type);
 600                          join("", @file) eq join("", @file2) or
 601                              die "error: $file does not match copy in package\n";
 602                          print "$file is okay\n";
 603                      } else {
 604                          spewfile($file, \@file, $type);
 605                      }
 606              
 607                      if ($cmd eq "edit" && $main::m) {
 608                          dprint "sd resolve3 $main::R \"$main::BeforeDir\\$unique\" \"$main::AfterDir\\$unique\" \"$destfile\" \"$destfile.out\"";
 609                          system("sd resolve3 $main::R \"$main::BeforeDir\\$unique\" \"$main::AfterDir\\$unique\" \"$destfile\" \"$destfile.out\"");
 610 krisbash 1.1             if (-e "$destfile.out") {
 611                              unlink $destfile;
 612                              rename "$destfile.out", $destfile;
 613                              chmod 0666, $destfile;
 614                          } else {
 615                              warn "warning: $destfile merge cancelled by user; skipped\n";
 616                          }
 617                          unlink "$main::BeforeDir\\$unique";
 618                          unlink "$main::AfterDir\\$unique";
 619                      }
 620              
 621                      if ($main::T && $atime && $mtime) {
 622                          utime $atime, $mtime, $destfile;
 623                      }
 624                  }
 625              }
 626              
 627              sub IsDirectoryEmpty {
 628                  my $dir = shift;
 629                  my $empty = 1;
 630                  if (opendir(D, $dir)) {
 631 krisbash 1.1         while ($file = readdir(D)) {
 632                          $empty = 0, last if $file ne '.' && $file ne '..';
 633                      }
 634                      closedir(D);
 635                  } else {
 636                      $empty = 0;         # Wacky directory, pretend nonempty so we skip it
 637                  }
 638                  $empty;
 639              }
 640              
 641              $main::NextUniqueDir = 0;
 642              
 643              sub GetNewTempDir {
 644                  my $TEMP = $ENV{"TEMP"} || $ENV{"TMP"};
 645                  die "error: no TEMP directory" unless $TEMP;
 646              
 647                  $TEMP =~ s/\\$//;     # avoid the \\ problem
 648              
 649                  # Look for suitable "before" and "after" directories; we'll
 650                  # call them "bbtmp###".
 651              
 652 krisbash 1.1     $TEMP .= "\\bbtmp";
 653              
 654                  while ($main::NextUniqueDir++ < 1000) {
 655                      my $try = "$TEMP$main::NextUniqueDir";
 656                      if (!-e $try && mkdir($try, 0777)) {
 657                          return $try;
 658                      }
 659                      if (-d _ && IsDirectoryEmpty($try)) {
 660                          return $try;
 661                      }
 662                  }
 663                  die "error: Too many ${TEMP}### directories\n";
 664              }
 665              
 666              sub CleanDir {
 667                  my $dir = shift;
 668                  if (defined($dir) && -e $dir) {
 669                      system "rd /q /s $dir";
 670                  }
 671              }
 672              
 673 krisbash 1.1 sub AccumulateCommonPrefix {
 674                  my $file = "/" . lc shift;
 675              
 676                  # Remove filename component
 677                  while ($file =~ s,[/\\][^/\\]*$,,) {
 678                      last unless defined $main::CommonPrefix;
 679                      last if substr($main::CommonPrefix, 0, length($file)) eq $file;
 680                  }
 681              
 682                  $main::CommonPrefix = $file;
 683              }
 684              
 685              #
 686              #   Okay, now initialize our globals.
 687              #
 688              
 689              $main::name = $0;
 690              $main::name =~ s/.*[\/\\:]//;
 691              $main::name =~ s/\.(bat|cmd)$//;
 692              
 693              $main::A = 0;
 694 krisbash 1.1 $main::B = 0;
 695              $main::c = "default";
 696              $main::d = 0;
 697              $main::f = 0;
 698              $main::l = 0;
 699              $main::m = 0;
 700              $main::n = 0;
 701              $main::R = "";
 702              $main::s = 0;
 703              $main::u = 0;
 704              $main::v = 0;
 705              $main::w = 0;
 706              $main::x = 0;
 707              $main::T = 0;
 708              $main::anyChanges = 0;
 709              
 710              $main::BeforeDir = undef;
 711              $main::AfterDir  = undef;
 712              %main::UniqueNames = ("" => 1); # preinit to avoid blank name
 713              $main::ExtraFlags = "";
 714              $main::fromDepot = undef;
 715 krisbash 1.1 $main::toDepot = undef;
 716              $main::CommonPrefix = undef;
 717              
 718              #
 719              #   WORKAROUND TO WORK AROUND PERL BUG IN <DATA> HANDLING.
 720              #   Reopen ourselves and advance to the raw data.
 721              #
 722              open(DATA, $0);
 723              0 until scalar(<DATA>) eq "__END__\n";
 724              
 725              my %PackerProperties;
 726              
 727              {
 728                  my $line;
 729                  while (($line = <DATA>) =~ /(.*?): (.*)/) {
 730              	if ($1 eq "Change Description") {
 731              	    $PackerProperties{$1} .= $2."\n";
 732              	} else {
 733              	    $PackerProperties{$1} = $2;
 734              	}
 735                  }
 736 krisbash 1.1     $main::pack = delete $PackerProperties{Packager};
 737                  die "error: corrupted package\n" unless $line eq "\n" && $main::pack;
 738                  die "error: your version of perl doesn't support lines longer than 256 characters\n"
 739                      unless $PackerProperties{"PerlSniffTest"} eq "." x 256;
 740              }
 741              
 742              #   If there is no command line and there is a BBUNPACKDEFCMD, use that
 743              #   variable instead.
 744              
 745              if ($#ARGV < 0 && defined $ENV{"BBUNPACKDEFCMD"}) {
 746                  my $cmd = $ENV{"BBUNPACKDEFCMD"};
 747                  $cmd =~ s/^\s+//;
 748                  while ($cmd =~ s/^\s*(?:"([^"]*)"|([^"]\S*))\s*//) {
 749                      push(@ARGV, $+);
 750                  }
 751              }
 752              
 753              while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) {
 754                  my $switch = shift;
 755                       if ($switch eq '-d') {
 756                      $main::d++;
 757 krisbash 1.1     } elsif ($switch eq '-f') {
 758                      $main::f++;
 759                  } elsif ($switch eq '-l') {
 760                      $main::l++;
 761                  } elsif ($switch eq '-m') {
 762                      $main::m++;
 763                      $main::fromDepot = shift;
 764                      $main::toDepot = shift;
 765              
 766                      if ($main::fromDepot !~ m#^//# ||
 767                          $main::toDepot !~ m#^//#) {
 768                          die "-m must be followed by two depot prefixes; type $name -? for help\n";
 769                      }
 770              
 771                  } elsif ($switch eq '-M') {
 772                      $main::m++;
 773                      $main::fromDepot = $main::toDepot = '/';
 774                  } elsif ($switch eq '-c') {
 775                      $main::c = shift;
 776              
 777                      if ($main::c !~ m#^[0-9]#) {
 778 krisbash 1.1             die "-c must be followed by a changelist number; type $name -? for help\n";
 779                      }
 780              
 781                  } elsif ($switch eq '-A') {
 782                      die "only one instance of -A allowed; type $name -? for help\n" if $main::A;
 783                      $main::A++;
 784                      $main::AfterDir = shift || die "-A requires an argument; type $name -? for help\n";
 785                  } elsif ($switch eq '-B') {
 786                      die "only one instance of -B allowed; type $name -? for help\n" if $main::B;
 787                      $main::B++;
 788                      $main::BeforeDir = shift || die "-B requires an argument; type $name -? for help\n";
 789                  } elsif ($switch eq '-n') {
 790                      $main::n++;
 791                  } elsif ($switch eq '-R') {
 792                      $main::R = shift;
 793                  } elsif ($switch eq '-s') {
 794                      $main::s++;
 795                  } elsif ($switch eq '-u') {
 796                      $main::u++;
 797                  } elsif ($switch eq '-v') {
 798                      $main::v++;
 799 krisbash 1.1     } elsif ($switch eq '-w') {
 800                      $main::w++;
 801                  } elsif ($switch eq '-x') {
 802                      $main::x++;
 803                  } elsif ($switch eq '-T') {
 804                      $main::T++;
 805                  } elsif ($switch eq '-?') {
 806                      Usage(); exit 1;
 807                  } else {
 808                      die "Invalid command line switch; type $name -? for help\n";
 809                  }
 810              }
 811              
 812              # Should be no command line options
 813              die "Invalid command line; type $main::name -? for help\n" if $#ARGV >= 0;
 814              
 815              die "Must specify an action; type -? for help\n"
 816                  unless $main::l || $main::s || $main::u || $main::v || $main::w;
 817              
 818              # suppress -w (presumably from registered .bpk extension)
 819              # if other actions found
 820 krisbash 1.1 $main::w = 0
 821                      if $main::l || $main::s || $main::u || $main::v;
 822              
 823              
 824              die "Cannot combine -m with -s\n" if $main::m && $main::s;
 825              die "Cannot combine -m with -w\n" if $main::m && $main::w;
 826              
 827              #
 828              #   -l wants some meta-information about the package.
 829              #
 830              if ($main::l) {
 831                  my $key;
 832                  foreach $key (split(/,/, "Comment,Client name,User name,Date,Change Description")) {
 833                      #
 834                      # Make sure to print blank properties for backwards compatability for
 835                      # anyone who parses the output.
 836                      #
 837                      if ($PackerProperties{$key}) {
 838                          map { print "$key: $_\n"; } split(/\n/, $PackerProperties{$key});
 839                      } else {
 840                          print "$key: $PackerProperties{$key}\n";
 841 krisbash 1.1         }
 842                  }
 843                  print "\n";
 844              }
 845              
 846              #
 847              #   See which files are open on the client.  This also establishes whether
 848              #   the server is up and the user has proper permissions.
 849              #
 850              my %OpenedFiles;
 851              
 852              if ($main::s || $main::u) {
 853                  # Intentionally let errors through to stderr
 854                  # Use -s to suppress stderr if no files are opened
 855                  foreach my $line (`sd.exe -s opened -c $main::c`) {
 856                      next if $line =~ m,^warning: , || $line =~ m,^exit: ,;
 857                      next if $line =~ m!^(error|warning): File\(s\) not opened !;
 858                      $line =~ m,^info: (//.*?)#(\d+|none),
 859                          or die "error: Cannot parse output of 'sd opened -c $main::c'\n";
 860                      $OpenedFiles{$1} = 1;
 861                      dprint "opened $1#$2";
 862 krisbash 1.1         $main::anyChanges = 1 if $' =~ /$main::c/;
 863                  }
 864              }
 865              
 866              die "error: changelist $main::c is not empty; use -f -u to unpack anyway\n"
 867                  if $main::anyChanges && $main::u && !$main::f;
 868              
 869              #
 870              #   The -w and -m options require us to set up some directories for unpacking.
 871              #
 872              if ($main::w || $main::m)
 873              {
 874                  $main::BeforeDir = GetNewTempDir() unless defined $main::BeforeDir;
 875                  $main::AfterDir  = GetNewTempDir() unless defined $main::AfterDir;
 876                  $main::ExtraFlags = " -p $PackerProperties{'Source Server Address'}";
 877              }
 878              
 879              #
 880              #   Go through each file in the package and perform an appropriate
 881              #   action on it.
 882              #
 883 krisbash 1.1 
 884              {
 885                  my @sync, @edit, @add, @delete;
 886              
 887                  my $line;
 888                  while (($line = <DATA>) =~ m|^(//.*?)#(\d+) (\S+) (\S+)|) {
 889              
 890                      #   $1 = depot path
 891                      #   $2 = rev
 892                      #   $3 = action
 893                      #   $4 = filetype (not currently used)
 894              
 895                      if ($main::l) {
 896                          print $line;
 897                      }
 898              
 899                      #   If sync'ing or unpacking, then the file had better not be open
 900                      #   since we're the ones who are going to open it.
 901              
 902                      die "error: $1 is already open on client; to merge, use the -M option\n"
 903                          if defined $OpenedFiles{$1} && ($main::s || ($main::u && !$main::m));
 904 krisbash 1.1 
 905                      #   If sync'ing, add to list of files that need to be sync'd.
 906                      #
 907                      #   If unpacking, then add to the appropriate list so we know
 908                      #   how to prepare the file for action.
 909              
 910                      if ($main::s) {
 911                          push(@sync, [ $1, $3 eq 'add' ? 'none' : $2 ]);
 912                      }
 913                      if ($main::u) {
 914              
 915                          my $path = $1;
 916                          if ($main::m) {
 917                              $path = Remap($1);
 918                          }
 919              
 920                          if ($path) {
 921                              if ($3 eq 'edit') {
 922                                  push(@edit, [ $path, $2 ]);
 923                              } elsif ($3 eq 'add') {
 924                                  push(@add, [ $path, $2 ]);
 925 krisbash 1.1                 } elsif ($3 eq 'delete') {
 926                                  push(@delete, [ $path, $2 ]);
 927                              } else {
 928                                  die "error: corrupted package\n";
 929                              }
 930                          }
 931                      }
 932              
 933                      AccumulateCommonPrefix($1);
 934              
 935                  }
 936                  die "error: corrupted package\n" unless $line eq "\n";
 937              
 938                  $main::CommonPrefix =~ s,^[/\\]+,,; # clean off leading slashes
 939              
 940                  if ($main::s || $main::u) {
 941              
 942                      #
 943                      #   Make sure that no files being added currently exist.
 944                      #
 945                      if ($#add >= 0) {
 946 krisbash 1.1             my $args = sdarg(undef, undef, \@add);
 947                          my $tempfile = CreateTempFile(@$args);
 948                          if (`sd.exe -x $tempfile have 2>nul`) {
 949                              unlink $tempfile;
 950                              die "error: adds in this package already exist on client\n";
 951                          }
 952                          unlink $tempfile;
 953                      }
 954              
 955                      #
 956                      #   Make sure that files being edited are the correct versions.
 957                      #
 958                      if (($#edit >= 0 || $#delete >= 0) && !$main::s && !$main::m) {
 959                          my @have = (@edit, @delete);
 960                          my %have;
 961                          my $file;
 962                          my $args = sdarg(undef, undef, \@have);
 963                          my $tempfile = CreateTempFile(@$args);
 964                          dprint "sd have @$args";
 965                          for $file (`sd.exe -x $tempfile have`) {
 966                              $file =~ m|(//.*?)#(\d+) - (.*)| or die "error: parsing output of 'sd have'\n";
 967 krisbash 1.1                 dprint "have $1#$2 - $3";
 968                              #
 969                              #    Store the have under both the depot path and the local path.
 970                              #
 971                              $have{lc $1} = $2;
 972                              $have{lc $3} = $2;
 973                          }
 974                          unlink $tempfile;
 975                          die "error: files to be edited/deleted do not exist on client\n" if $?;
 976                          for $file (@have) {
 977                              die "error: wrong version of $file->[0] on client\n"
 978                                  if $have{lc $file->[0]} ne $file->[1];
 979                          }
 980                      }
 981              
 982                      sdaction("sync#", \@sync);
 983                      sdaction("edit -c $main::c", \@edit);
 984                      # Do not do the adds yet; wait until after the edits have been applied
 985                      sdaction("delete -c $main::c", \@delete);
 986                  }
 987              
 988 krisbash 1.1     #
 989                  #   Now go extract the actual files.
 990                  #
 991                  if (!$main::n && ($main::u || $main::v || $main::w)) {
 992                      my $line;
 993                      # " *" because some editors trim trailing spaces
 994                      while (($line = <DATA>) =~ m|^(//.*?)#(\d+) (\S+) (\S+) *(\d*) *(\d*)|) {
 995                          ApplyEdit($1, $2, $3, $4, $5, $6);
 996                      }
 997                  }
 998              
 999                  # Okay, now do the adds now that the output files have been created
1000                  sdaction("add -c $main::c", \@add);
1001              }
1002              
1003              if ($main::w) {
1004                  my $windiff = $ENV{"BBDIFF"} || $ENV{"SDDIFF"} || "windiff";
1005                  system("$windiff \"$main::BeforeDir\" \"$main::AfterDir\"");
1006              }
1007              
1008              CleanDir($main::BeforeDir) unless $main::B;
1009 krisbash 1.1 CleanDir($main::AfterDir) unless $main::A;
1010              
1011              __END__
1012              PerlSniffTest: ................................................................................................................................................................................................................................................................
1013              Packager: bbpack
1014              Client name: GIRISHJO-WIN8-130514165419
1015              User name: REDMOND\girishjo
1016              Source Server Address: TK5SDSERVWIN13.sys-wingroup.ntdev.corp.microsoft.com:2002
1017              Server address: TK5SDSERVWIN13.sys-wingroup.ntdev.corp.microsoft.com:2002
1018              Date: 2013/09/20 18:19:32
1019              
1020              //depot/fbl_srv2_obi_mi_dev_r2_r1/admin/wmi/winomi/base/log.c#11 edit text
1021              
1022              //depot/fbl_srv2_obi_mi_dev_r2_r1/admin/wmi/winomi/base/log.c#11 edit text 1376954826 1379726281
1023              a198 4
1024              #if defined(CONFIG_OS_WINDOWS)
1025              #include <share.h>
1026              #endif
1027              
1028              d208 1
1029              a208 2
1030 krisbash 1.1         _os = _fsopen(path, "a", _SH_DENYWR);
1031                      if (_os == NULL)
1032              d215 1
1033              a215 2
1034                      _os = _wfsopen(path, L"a", _SH_DENYWR);
1035                      if (_os == NULL)
1036              q

ViewCVS 0.9.2