Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
7.0 KiB

  1. @echo off
  2. for %%i in (%0.cmd) do perl -w -x %%~dp$PATH:i%0.cmd %*
  3. goto :eof
  4. #!perl
  5. # line 6
  6. #
  7. # FileName: sdbackup.cmd
  8. #
  9. # Usage = sdbackup [-v] [-d altdir] <backupdir>
  10. #
  11. # Enumerates all the SD opened files in all depots and copies the
  12. # changes out to the specified path. This can be useful simply as
  13. # a regular backup of local changes, or as a mechanism for sharing
  14. # private changes with another person.
  15. #
  16. # Example:
  17. # sdbackup \\scratch\scratch\jvert\sdbackup
  18. # copies all opened files to \\scratch\scratch\jvert\sdbackup\<currentdate>
  19. # sdbackup -d newchange \\scratch\scratch\jvert
  20. # copies all opened files to \\scratch\scratch\jvert\newchange
  21. #
  22. #
  23. use Getopt::Std;
  24. use File::Path;
  25. use File::Spec;
  26. use File::Copy;
  27. #
  28. # initialize globals
  29. #
  30. $opt_v = 0;
  31. $opt_d = 0;
  32. %revisionlist = ();
  33. %changelist = ();
  34. %clientfilelist = ();
  35. $Usage = "
  36. USAGE: $0 [-v] [-d altdir] [backupdir]
  37. -v Verbose output
  38. -d altdir use <altdir> instead of <currentdate> as the root directory
  39. backupdir Supplies directory where files will be backed up to.
  40. The directory structure created will look like this:
  41. <backupdir>\<currentdate>
  42. backup.log - list of files and their versions
  43. \\nt\.. - directories and files
  44. If -n is specified, the directory structure will look
  45. like this:
  46. <backupdir>\\nt.. - directories and files
  47. If not specified, the filenames will just be printed to stdout.\n";
  48. #
  49. # Finds the full filenames of all checked out files
  50. #
  51. getopts('vd:') or die $Usage;
  52. $backupdir = $ARGV[0];
  53. $opt_v and print("backupdir is $backupdir\n");
  54. foreach $line (`sdx opened`) {
  55. chomp $line;
  56. #
  57. # throw away blank lines, depot specifiers, and empty lists
  58. #
  59. $line =~ /^[\t\s]*$|^------|^File\(s\) not opened/ and next;
  60. #
  61. # throw away files that aren't in the default change list. Kind of sleazy,
  62. # but it prevents the public libraries from getting in the list
  63. #
  64. $line =~ /edit change \d/ and next;
  65. #
  66. # throw away deleted files
  67. #
  68. $line =~ /delete default change/ and next;
  69. #
  70. # If we hit the summary, we're done
  71. #
  72. $line =~ /^== Summary/ and last;
  73. $opt_v and print ("line = $line\n");
  74. #
  75. # parse the resulting filename
  76. #
  77. ($depotfilename, $revision, $change) = split(/#| - /,$line);
  78. $opt_v and print ("\tfilename: $depotfilename\n\trevision: $revision\n\tchange: $change\n\n");
  79. $depotfilename = lc($depotfilename);
  80. $revisionlist{$depotfilename} = $revision;
  81. $changelist{$depotfilename} = $change;
  82. }
  83. #
  84. # Now we have a list of depot names. Translate those into clientnames
  85. # by calling sdx where
  86. #
  87. # note: since the command line can only accept a limited # of files
  88. # to run "sdx where" on, we break up the command into multiple
  89. # smaller "sdx where" runs.
  90. #
  91. $s = "";
  92. $r = [keys(%revisionlist)];
  93. $maxArgSize = 200;
  94. foreach $revision (0..$#$r) {
  95. # get the combination of the existing list + the current revision
  96. $k = $s." ".$$r[$revision];
  97. # if the list is too long then it's time to process it
  98. # if we are at the end of the list, then we need to flush the list
  99. if ((length($k) > $maxArgSize) || ($revision == $#$r)) {
  100. #
  101. # pass:
  102. # 0: do the existing list in $s
  103. # 1: do the current revision
  104. #
  105. $firstPass = 1;
  106. while(1) {
  107. # skip first iteration if $s is empty
  108. # this implies that the current revision
  109. # is > 200 chars and may not work
  110. if ($s ne "") {
  111. if (length($s) > $maxArgSize) {
  112. print "warning: attempting to process long revision: $revision\n";
  113. }
  114. foreach $line (`sdx where $s`) {
  115. #
  116. # throw away blank lines, depot specifiers, "not found" lines,
  117. # and lines that start with "-"
  118. #
  119. $line =~ /^[\t\s]*$|^-------|file\(s\) not in client view|^-/ and next;
  120. chomp $line;
  121. $opt_v and print("mapping: $line\n");
  122. ($depotfilename, $trash, $clientfilename) = split(/\s/,$line);
  123. $depotfilename = lc($depotfilename);
  124. $clientfilelist{$depotfilename} = lc($clientfilename);
  125. -e $clientfilename or die "file: $clientfilename should exist but doesn't!\n";
  126. }
  127. }
  128. if (! $firstPass) {
  129. last;
  130. }
  131. $s = $$r[$revision];
  132. $firstPass = 0;
  133. }
  134. $s = "";
  135. } else {
  136. $s = $k;
  137. }
  138. }
  139. #
  140. # make sure we have as many client file list entries as revision entries
  141. #
  142. $temp = [(keys %clientfilelist)];
  143. if ($#$temp != $#$r) {
  144. print "error occured while compiling client file list\n";
  145. print $#$temp ." vs. ". $#$r ."\n";
  146. die;
  147. }
  148. if ($backupdir) {
  149. if ($opt_d) {
  150. $backupdir .= "\\$opt_d";
  151. } else {
  152. @time = localtime;
  153. $backupdir .= sprintf("\\%4d-%02d-%02d.%02d%02d",($time[5]+1900),$time[4]+1,$time[3],$time[2],$time[1]);
  154. $opt_v and print $backupdir."\n";
  155. }
  156. mkpath($backupdir) unless -d $backupdir;
  157. open(LOGFILE, "+> $backupdir\\backup.log") or die "Couldn't open $backupdir\\backup.log: $!\n";
  158. #
  159. # Write all the files to backup.log. Format is:
  160. # SDfilename #<versionnumber> clientfilename
  161. #
  162. foreach $file (sort keys %clientfilelist) {
  163. $clientfile = $clientfilelist{$file};
  164. #
  165. # Each client filename is in the form X:<full pathname>\<filename>
  166. # Split this up into volume, path, filename components (we don't
  167. # care about the volume)
  168. #
  169. ($trash,$dir,$filename) = File::Spec->splitpath($clientfile);
  170. #
  171. # Write this file's data to the logfile
  172. #
  173. $srcfile = File::Spec->catfile($dir, $filename);
  174. print LOGFILE "$file #$revisionlist{$file} $srcfile\n";
  175. #
  176. # compute the destination directory and make sure it exists.
  177. #
  178. $destdir = File::Spec->catdir($backupdir, $dir);
  179. -d $destdir || mkpath($destdir) or die "Couldn't create destination directory $destdir: $!\n";
  180. #
  181. # compute the full destination path and filename
  182. #
  183. $destfile = File::Spec->catfile($destdir, $filename);
  184. if ($opt_v) {
  185. print("copying $clientfile to $destfile\n");
  186. } else {
  187. print("$clientfile\n");
  188. }
  189. copy($clientfile, $destfile, 0)
  190. or die "Couldn't copy $clientfile -> $destfile: $!\n";
  191. }
  192. } else {
  193. print join("\n", sort values %clientfilelist);
  194. }