| 1293 |
dpurdie |
1 |
#!c:/perl/bin/perl.exe -w
|
|
|
2 |
|
|
|
3 |
###############################################################################
|
|
|
4 |
# Codestriker: Copyright (c) 2001 - 2004 David Sitsky. All rights reserved.
|
|
|
5 |
# sits@users.sourceforge.net
|
|
|
6 |
#
|
|
|
7 |
# This program is free software; you can redistribute it and modify it under
|
|
|
8 |
# the terms of the GPL.
|
|
|
9 |
|
|
|
10 |
# Perl script for creating a single diff file over a Visual SourceSafe
|
|
|
11 |
# project, in a suitable form that can be input as a Codestiker
|
|
|
12 |
# (http://codestriker.sourceforge.net) topic.
|
|
|
13 |
|
|
|
14 |
###############################################################################
|
|
|
15 |
# Script configuration.
|
|
|
16 |
|
|
|
17 |
# If no argument is passed to the script, this is the SourceSafe
|
|
|
18 |
# project which will be used. Modify this to reflect your own usage.
|
|
|
19 |
my $ss_project = '$/Project';
|
|
|
20 |
|
|
|
21 |
# Set this to the path of your ss.exe executable.
|
|
|
22 |
my $ss = 'C:/Program Files/Microsoft Visual Studio/VSS/win32/ss.exe';
|
|
|
23 |
|
|
|
24 |
# Specify the SS username and password to use when running ss.exe
|
|
|
25 |
# commands.
|
|
|
26 |
my $ss_username = 'admin';
|
|
|
27 |
my $ss_password = 'password';
|
|
|
28 |
|
|
|
29 |
# Specify the location of the SS repository. If this is left empty
|
|
|
30 |
# then the SSDIR environment variable will not be set, and ss.exe will
|
|
|
31 |
# use the default repository.
|
|
|
32 |
my $ssdir = '';
|
|
|
33 |
#my $ssdir = '\\\\VisualSourceSafeMachineName\\SharedRepositoryPath';
|
|
|
34 |
#my $ssdir = 'c:\\Program Files\\Microsoft Visual Studio\\VSS';
|
|
|
35 |
|
|
|
36 |
# Set this to 1 to see all the SS commands being executed.
|
|
|
37 |
my $verbose = 0;
|
|
|
38 |
|
|
|
39 |
# End script configuration.
|
|
|
40 |
###############################################################################
|
|
|
41 |
|
|
|
42 |
use strict;
|
|
|
43 |
use File::Temp qw/ tmpnam tempdir /;
|
|
|
44 |
|
|
|
45 |
# First, check if an argument has been passed, which overrides
|
|
|
46 |
# $ss_project.
|
|
|
47 |
if ($#ARGV == 0) {
|
|
|
48 |
$ss_project = $ARGV[0];
|
|
|
49 |
} elsif ($#ARGV > 0) {
|
|
|
50 |
print STDERR "usage: ssdiff.pl [SourceSafe Project] > file.txt\n";
|
|
|
51 |
print STDERR " SourceSafe Project defaulted to $ss_project\n";
|
|
|
52 |
exit 1;
|
|
|
53 |
}
|
|
|
54 |
|
|
|
55 |
# Create a temporary directory where all of the temporary files
|
|
|
56 |
# will be written to. This iwll be automatically removed when the
|
|
|
57 |
# script exits.
|
|
|
58 |
my $tempdir;
|
|
|
59 |
if (defined $Codestriker::tmpdir && $Codestriker::tmpdir ne "") {
|
|
|
60 |
$tempdir = tempdir(DIR => $Codestriker::tmpdir, CLEANUP => 1);
|
|
|
61 |
}
|
|
|
62 |
else {
|
|
|
63 |
$tempdir = tempdir(CLEANUP => 1);
|
|
|
64 |
}
|
|
|
65 |
|
|
|
66 |
# Set the SSDIR environment variable if necessary.
|
|
|
67 |
if (defined $ssdir && $ssdir ne '')
|
|
|
68 |
{
|
|
|
69 |
$ENV{SSDIR} = $ssdir;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
# Now execute an 'ss dir' command to determine what files are a part
|
|
|
73 |
# of this project.
|
|
|
74 |
if ($verbose) {
|
|
|
75 |
print STDERR "\"$ss\" dir -y${ss_username},${ss_password}" .
|
|
|
76 |
" -R -I-Y \"$ss_project\"\n";
|
|
|
77 |
}
|
|
|
78 |
open(VSS, "\"$ss\" dir -y${ss_username},${ss_password}" .
|
|
|
79 |
" -R -I-Y \"$ss_project\" |") || die "Unable to run ss diff command: $!";
|
|
|
80 |
|
|
|
81 |
# Collect the list of filename and revision numbers into a list.
|
|
|
82 |
my @files = ();
|
|
|
83 |
my $current_dir = '';
|
|
|
84 |
my $top_dir;
|
|
|
85 |
while (<VSS>) {
|
|
|
86 |
if (/^(\$\/.*):$/o) {
|
|
|
87 |
# Entering a new top-level directory.
|
|
|
88 |
$current_dir = $1;
|
|
|
89 |
$top_dir = $1 unless defined $top_dir;
|
|
|
90 |
} elsif (/^\$[^\/]/o) {
|
|
|
91 |
# Sub-directory entry which can be skipped.
|
|
|
92 |
} elsif (/^\d+ item/o) {
|
|
|
93 |
# Item count line which can be skipped.
|
|
|
94 |
} elsif (/^\s*$/o) {
|
|
|
95 |
# Skip blank lines.
|
|
|
96 |
} elsif (/^(.*)$/o) {
|
|
|
97 |
# Actual file entry.
|
|
|
98 |
push @files, "$current_dir/$1";
|
|
|
99 |
}
|
|
|
100 |
}
|
|
|
101 |
close VSS;
|
|
|
102 |
|
|
|
103 |
my $top_dir_length = length($top_dir);
|
|
|
104 |
|
|
|
105 |
# Now for each text file, we need to run an 'ss diff' command to see
|
|
|
106 |
# what contents have changed.
|
|
|
107 |
for (my $i = 0; $i <= $#files; $i++) {
|
|
|
108 |
# Determine if the file is a text file, and if not, skip it.
|
|
|
109 |
# Also determine its version number.
|
|
|
110 |
if ($verbose) {
|
|
|
111 |
print STDERR "\"$ss\" properties \"$files[$i]\"" .
|
|
|
112 |
" -y${ss_username},${ss_password} -I-Y\n";
|
|
|
113 |
}
|
|
|
114 |
open(VSS, "\"$ss\" properties \"$files[$i]\"" .
|
|
|
115 |
" -y${ss_username},${ss_password} -I-Y |")
|
|
|
116 |
|| die "Unable to run ss properties on $files[$i]\n";
|
|
|
117 |
my $text_type = 0;
|
|
|
118 |
my $version;
|
|
|
119 |
while (<VSS>) {
|
|
|
120 |
if (/Type:\s*Text/o) {
|
|
|
121 |
$text_type = 1;
|
|
|
122 |
} elsif (/^ Version:\s+(\d+)\s/o) {
|
|
|
123 |
$version = $1;
|
|
|
124 |
}
|
|
|
125 |
}
|
|
|
126 |
close(VSS);
|
|
|
127 |
next if $text_type == 0;
|
|
|
128 |
die "Couldn't get version for $files[$i]\n" unless defined $version;
|
|
|
129 |
|
|
|
130 |
# Now need to construct the path to the real file from the SS path.
|
|
|
131 |
# First we need to remove the project part from the full "path".
|
|
|
132 |
my $real_file = substr($files[$i], $top_dir_length+1);
|
|
|
133 |
if (! defined $real_file) {
|
|
|
134 |
die "Can't extract filename from $files[$i] top_dir $top_dir\n";
|
|
|
135 |
}
|
|
|
136 |
|
|
|
137 |
# Translate the forward slashes to back slashes.
|
|
|
138 |
$real_file =~ s/\//\\/g;
|
|
|
139 |
|
|
|
140 |
# If there are no slashes in the filename, we need to add .\ in the
|
|
|
141 |
# front. Don't ask!
|
|
|
142 |
if ($real_file !~ /\\/o) {
|
|
|
143 |
$real_file = ".\\" . $real_file;
|
|
|
144 |
}
|
|
|
145 |
|
|
|
146 |
print STDERR "Diffing $real_file against $files[$i]\n";
|
|
|
147 |
|
|
|
148 |
# Note the command has to be redirected to a file, otherwise the ss
|
|
|
149 |
# command will wrap the lines.
|
|
|
150 |
my $command_output = "$tempdir\\___output.txt";
|
|
|
151 |
if ($verbose) {
|
|
|
152 |
print STDERR "\"$ss\" diff -y${ss_username},${ss_password} -I-Y" .
|
|
|
153 |
" -DU3000X5 -O\"$command_output\" \"$files[$i]\" \"$real_file\"\n";
|
|
|
154 |
}
|
|
|
155 |
system("\"$ss\" diff -y${ss_username},${ss_password} -I-Y" .
|
|
|
156 |
" -DU3000X5 -O\"$command_output\" \"$files[$i]\" \"$real_file\"");
|
|
|
157 |
if (open(VSS, $command_output)) {
|
|
|
158 |
# Because ss doesn't include the version number of the file we are
|
|
|
159 |
# diffing against, we have to do so here.
|
|
|
160 |
my $first_line = <VSS>;
|
|
|
161 |
chop $first_line;
|
|
|
162 |
print STDOUT "$first_line;$version\n";
|
|
|
163 |
while (<VSS>) {
|
|
|
164 |
print STDOUT $_;
|
|
|
165 |
}
|
|
|
166 |
close VSS;
|
|
|
167 |
}
|
|
|
168 |
unlink $command_output;
|
|
|
169 |
}
|
|
|
170 |
|
|
|
171 |
|