Deletes old autobuilder files.

Deletes old dds_analyse.pl script.
Updates tools LICENSE.txt

This was SVN commit r16435.
This commit is contained in:
historic_bruno 2015-03-15 22:18:02 +00:00
parent 333c4401b9
commit 99cb4b42fd
28 changed files with 1 additions and 2407 deletions

View File

@ -8,27 +8,15 @@ in particular, let us know and we can try to clarify it.
atlas
GPL version 2 (or later) - see license_gpl-2.0.txt
autobuild
MIT
autobuild2
Various (unspecified)
autolog
MIT
cmpgraph
MIT
dds
MIT
dist
MIT
entconvert
MIT
entdocs
MIT
@ -86,4 +74,4 @@ in particular, let us know and we can try to clarify it.
MIT
XpartaMuPP
GPLv2
GPL version 2 (or later)

View File

@ -1,266 +0,0 @@
# Build script - does the actual building of the project
use strict;
use warnings;
use constant EXIT_BUILDCOMPLETE => 0;
use constant EXIT_NOTCOMPILED => 1;
use constant EXIT_FAILED => 2;
use constant EXIT_ABORTED => 3;
my $svn_trunk = 'c:\0ad\trunk';
#my $temp_trunk = 'r:\trunk';
my $temp_trunk = 'c:\0ad\buildtrunk';
my $output_dir = 'c:\0ad\builds';
my $log_dir = 'c:\0ad\autobuild';
my $doc_out_dir = 'p:\latest';
my $sevenz = '"C:\Program Files\7-Zip\7z.exe"';
my $junction = 'c:\0ad\autobuild\junction.exe'; # from http://www.sysinternals.com/Utilities/Junction.html
#my $vcbuild = '"C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\vcbuild"';
# except I need to call vcvars32.bat then "vcbuild.exe /useenv", since the VS registry settings don't always exist
my $vcbuild = '"C:\0ad\autobuild\vcbuild_env.bat"';
my $time_start = time();
eval { # catch deaths
# Capture all output
open STDOUT, '>', "$log_dir\\build_stdout_temp.txt";
open STDERR, '>', "$log_dir\\build_stderr_temp.txt";
open BUILDLOG, '>', "$log_dir\\buildlog_temp.txt" or die $!;
our ($username, $password);
do 'login_details.pl' or die "Cannot find login details: $! / $@";
# login_details.pl contains:
# $::username = "philip";
# $::password = "something";
# (but with a valid password, which I'm not going to tell you)
add_to_buildlog("Starting build at ".(gmtime($time_start))." GMT.\n");
chdir $svn_trunk or die $!;
if (grep { $_ eq '--commitlatest' } @ARGV)
{
add_to_buildlog("Committing latest code");
### Find the latest revision number ###
opendir my $dir, $output_dir or die $!;
my @revs = grep /^\d+$/, readdir $dir;
die unless @revs;
my $rev = (sort { $b <=> $a } @revs)[0];
add_to_buildlog("Committing ps.exe for revision $rev");
### Copy ps.exe and ps.pdb over the SVN copy ###
`copy $output_dir\\$rev\\ps.exe $svn_trunk\\binaries\\system\\`;
die $? if $?;
`copy $output_dir\\$rev\\ps.pdb $svn_trunk\\binaries\\system\\`;
die $? if $?;
### Commit ps.exe and ps.pdb ###
my $svn_output = `svn commit binaries\\system\\ps.exe binaries\\system\\ps.pdb --username $username --password $password --message "Automated build." 2>&1`;
add_to_buildlog($svn_output);
die $? if $?;
# Just exit, and don't overwrite the earlier logs
exit(EXIT_NOTCOMPILED);
}
### Update from SVN ###
my $svn_output = `svn update --username $username --password $password 2>&1`;
add_to_buildlog($svn_output);
die $? if $?;
allow_abort();
$svn_output =~ /^(?:Updated to|At) revision (\d+)\.$/m or die;
my $svn_revision = $1;
if ($svn_output =~ m~^. (source(?![/\\](tools(?![/\\]atlas[/\\]GameInterface)|collada))|build|libraries)~m)
{
# The source has been updated.
# ('source' means something in the source, build, or libraries directories, excluding source/tools, but including source/tools/atlas/GameInterface)
}
else
{
# Nothing's changed. Build anyway?
if (grep { $_ eq '--force' } @ARGV)
{
# Yes
}
else
{
add_to_buildlog("*** Build $svn_revision not needed - no source changes ***");
# Just exit, and don't overwrite the earlier logs
exit(EXIT_NOTCOMPILED);
}
}
### Check whether we've already built this ###
if (-e "$output_dir\\$svn_revision")
{
add_to_buildlog("*** Build $svn_revision already exists ***");
# Just exit, and don't overwrite the earlier logs
exit(EXIT_NOTCOMPILED);
}
### Clean the RAM disk ###
`rmdir /q /s $temp_trunk 2>&1`;
# ignore failures - the RAM disk might have been recently reset
### Copy all the necessary files onto it ###
# For some directories (which we're going to alter), do a real copy
for (qw(build))
{
`xcopy /e $svn_trunk\\$_ $temp_trunk\\$_\\ 2>&1`;
die "xcopy $_: $?" if $?;
allow_abort();
}
# For other directories (which we're only going to read), do a 'junction' (like a symbolic link) because it's faster
for (qw(source libraries))
{
`$junction $temp_trunk\\$_ $svn_trunk\\$_`;
die "junction $_: $?" if $?;
allow_abort();
}
### Create the workspace files ###
chdir "$temp_trunk\\build\\workspaces" or die $!;
my $updateworkspaces_output = `update-workspaces.bat 2>&1`;
add_to_buildlog($updateworkspaces_output);
die $? if $?;
### Create target directories for built files ###
mkdir "$temp_trunk\\binaries" or die $!;
mkdir "$temp_trunk\\binaries\\system" or die $!;
allow_abort();
### Do the Testing build ###
my $build_output1 = `$vcbuild /time vc2003\\pyrogenesis.sln Testing 2>&1`;
add_to_buildlog($build_output1);
die $? if ($? and $? != 32768); # 32768 seems to be returned when it succeeds
allow_abort();
### Copy the output ###
`mkdir $output_dir\\temp`;
# ignore failures - this might already exist if the last build was aborted
`copy $temp_trunk\\binaries\\system\\ps_test.exe $output_dir\\temp\\`;
die $? if $?;
`copy $temp_trunk\\binaries\\system\\ps_test.pdb $output_dir\\temp\\`;
die $? if $?;
### Clean up unnecessary files to save space ###
`rmdir /q /s $temp_trunk\\build\\workspaces\\vc2003\\obj\\Testing 2>&1`;
die $? if $?;
`rmdir /q /s $temp_trunk\\binaries 2>&1`;
die $? if $?;
allow_abort();
### Recreate targets for built files ###
mkdir "$temp_trunk\\binaries" or die $!;
mkdir "$temp_trunk\\binaries\\system" or die $!;
### Do the Release build ###
my $build_output2 = `$vcbuild /time vc2003\\pyrogenesis.sln Release 2>&1`;
add_to_buildlog($build_output2);
die $? if ($? and $? != 32768);
### Copy the output ###
`copy $temp_trunk\\binaries\\system\\ps.exe $output_dir\\temp\\`;
die $? if $?;
`copy $temp_trunk\\binaries\\system\\ps.pdb $output_dir\\temp\\`;
die $? if $?;
### Generate the documentation ###
chdir "$temp_trunk\\build\\docs" or die $!;
`builddoc.bat`;
if ($?)
{
warn $?;
}
else
{
### Store the documentation ###
`rmdir /q /s $doc_out_dir 2>&1`;
`xcopy /e $temp_trunk\\docs\\generated\\*.* $doc_out_dir\\ 2>&1`;
}
### Store the output permanently ###
rename "$output_dir\\temp", "$output_dir\\$svn_revision" or die $!;
### and make a compressed archive ###
chdir "$output_dir\\$svn_revision" or die $!;
`$sevenz a -mx7 -bd -sfx7zC.sfx ..\\$svn_revision.exe`;
die $? if $?;
# (TODO: delete the non-archived data when it's not needed, to save disk space)
}; # end of eval
if ($@)
{
warn $@;
quit(EXIT_FAILED);
}
else
{
quit(EXIT_BUILDCOMPLETE);
}
# Exit, after copying the current log files over the previous ones
sub quit
{
my $time_end = time();
my $time_taken = $time_end - $time_start;
add_to_buildlog("\nBuild completed at ".(gmtime($time_end))." GMT - took $time_taken seconds.");
close BUILDLOG;
rename "$log_dir\\buildlog_temp.txt", "$log_dir\\buildlog.txt" or die $!;
close STDOUT;
rename "$log_dir\\build_stdout_temp.txt", "$log_dir\\build_stdout.txt" or die $!;
close STDERR;
rename "$log_dir\\build_stderr_temp.txt", "$log_dir\\build_stderr.txt" or die $!;
exit($_[0]);
}
sub add_to_buildlog
{
print BUILDLOG "$_[0]\n--------------------------------------------------------------------------------\n";
}
# Call this at strategic moments, to allow builds to be aborted (when e.g. there's another revision just come in that needs to be built instead)
sub allow_abort
{
if (-e "$log_dir\\build_abort")
{
add_to_buildlog("*** Build aborted ***\n");
unlink "$log_dir\\build_abort";
quit(EXIT_ABORTED);
}
}

View File

@ -1,300 +0,0 @@
# Build daemon - receives notifications of commits, runs the build process (ensuring there's only one copy at once), commits the built files, and provides access to all earlier builds and the build log of the latest.
use warnings;
use strict;
# Exit codes used by build.pl:
use constant EXIT_BUILDCOMPLETE => 0;
use constant EXIT_NOTCOMPILED => 1;
use constant EXIT_FAILED => 2;
use constant EXIT_ABORTED => 3;
use POE qw(Component::Server::TCP Component::Client::HTTP Filter::HTTPD Filter::Line);
use HTTP::Response;
use Win32::Process;
my $build_process; # stores Win32::Process handle
my $build_required = 0; # set by commits, cleared by builds; 1 for normal build, 2 for forced build (even if no source was changed)
my $commit_required = 0; # stores the time when it should happen, or 0 if never
my $build_start_time; # time that the most recent build started
my $last_exit_code; # exit code of the most recent completed build
my $build_active = 0; # 0 => build process not running; 1 => build process running within the past second
use constant COMMIT_DELAY => 60*60; # seconds to wait after a code commit before committing ps.exe
open my $logfile, '>>', 'access_log' or die "Error opening access_log: $!";
$logfile->autoflush();
sub LOG {
my ($pkg, $file, $line) = caller;
my $msg = localtime()." - $file:$line - @_\n";
print $logfile $msg;
print $msg;
}
my $main_session; # main POE::Session object
POE::Component::Server::TCP->new(
Alias => "web_server",
Port => 57470,
ClientFilter => 'POE::Filter::HTTPD',
ClientInput => sub {
my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0];
# Respond to errors in the client's request
if ($request->isa("HTTP::Response")) {
$heap->{client}->put($request);
$kernel->yield("shutdown");
return;
}
LOG $heap->{remote_ip}." - ".$request->uri->as_string;
my $response = HTTP::Response->new(200);
my $url = $request->uri->path;
if ($url eq '/commit_notify.html')
{
$build_required = 1;
abort_build();
$response->push_header('Content-type', 'text/plain');
$response->content("Build initiated.");
$kernel->post($main_session, 'commit_notify');
}
elsif ($url eq '/force_build.html')
{
$build_required = 2;
abort_build();
$response->push_header('Content-type', 'text/plain');
$response->content("Forced build initiated.");
}
elsif ($url eq '/commit_latest.html')
{
$commit_required = time();
$response->push_header('Content-type', 'text/plain');
$response->content("Commit initiated.");
}
elsif ($url eq '/abort_build.html')
{
abort_build();
$response->push_header('Content-type', 'text/plain');
$response->content("Build aborted.");
}
elsif ($url eq '/status.html')
{
$response->push_header('Content-type', 'text/html');
my $text = <<EOF;
<html><body>
@{[ $build_active ? "Build in progress - ".(time()-$build_start_time)." seconds elapsed." : "Build not in progress." ]}
<br><br>
Last build status: @{[do{
if ($last_exit_code == EXIT_BUILDCOMPLETE or $last_exit_code == EXIT_NOTCOMPILED) {
"Succeeded";
} elsif ($last_exit_code == EXIT_ABORTED) {
"Aborted"
} else {
"FAILED ($last_exit_code)"
}
}]}.
<br><br>
Build log: (<a href="logs.html">complete logs</a>)
<br><br>
EOF
my $buildlog = do { local $/; my $f; open $f, 'buildlog.txt' and <$f> };
if ($buildlog)
{
$buildlog =~ s/&/&amp;/g;
$buildlog =~ s/</&lt;/g;
$buildlog =~ s/>/&gt;/g;
}
else
{
$buildlog = "(Error opening build log)";
}
$text .= "<pre>$buildlog</pre>";
$text .= qq{</body></html>};
$response->content($text);
}
elsif ($url eq '/logs.html')
{
$response->push_header('Content-type', 'text/plain');
my $text;
for my $n (qw(buildlog build_stdout build_stderr))
{
my $filedata = do { local $/; my $f; open $f, "$n.txt" and <$f> };
$text .= "--------------------------------------------------------------------------------\n";
$text .= "$n\n";
$text .= "--------------------------------------------------------------------------------\n";
$text .= $filedata;
$text .= "\n\n\n";
}
$response->content($text);
}
elsif ($url eq '/filelist.html')
{
my $output = '';
eval {
opendir my $d, "..\\builds" or die $!;
my @revs;
for (grep /^\d+\.exe$/, readdir $d)
{
/^(\d+)/;
push @revs, $1;
}
$output .= qq{<a href="download/$_.exe">$_</a> (}.int( (stat "..\\builds\\$_.exe")[7]/1024 ).qq{k)\n} for sort { $b <=> $a } @revs;
};
if ($@)
{
LOG "filelist failed: $@";
$response->push_header('Content-type', 'text/plain');
$response->content("Internal error.");
}
else
{
$response->push_header('Content-type', 'text/html');
$response->content("<html><body><pre>$output</pre></body></html>");
}
}
elsif ($url =~ m~/download/(\d+).exe~)
{
my $rev = $1;
if (-e "..\\builds\\$rev.exe" and open my $f, "..\\builds\\$rev.exe")
{
binmode $f;
$response->push_header('Content-type', 'application/octet-stream');
$response->content(do{local $/; <$f>});
}
else
{
LOG "Error serving file $url";
$response->push_header('Content-type', 'text/plain');
$response->content("File not found.");
}
}
elsif ($url eq '/favicon.ico')
{
$response = HTTP::Response->new(404);
$response->push_header('Content-type', 'text/html');
$response->content($response->error_as_HTML);
}
else
{
$response->push_header('Content-type', 'text/plain');
$response->content("Unrecognised request.");
}
$heap->{client}->put($response);
$kernel->yield("shutdown");
},
);
POE::Component::Client::HTTP->spawn(
Alias => "web_client",
);
$main_session = POE::Session->create(
inline_states => {
_start => sub {
$_[KERNEL]->delay(tick => 1);
},
tick => sub {
$_[KERNEL]->delay(tick => 1);
if ($build_active and not build_is_running())
{
# Build has just completed.
$last_exit_code = get_exit_code();
$build_active = 0;
undef $build_process;
LOG "Build complete ($last_exit_code)";
if ($last_exit_code == EXIT_BUILDCOMPLETE)
{
$commit_required = $build_start_time + COMMIT_DELAY;
}
else
{
$commit_required = 0;
}
}
if ($build_required and not $build_active)
{
start_build(force => ($build_required == 2));
}
elsif ($commit_required and time() >= $commit_required)
{
start_build(commit => 1);
$commit_required = 0;
}
},
commit_notify => sub {
$_[KERNEL]->post('web_client', 'request', 'commit_notify_response',
new HTTP::Request(GET => 'http://192.168.0.223/wfg/svnlog.cgi/logupdate/doupdate'));
},
commit_notify_response => sub {
my $response_packet = $_[ARG1];
my $response = $response_packet->[0];
LOG "notified - ".$response->content;
},
}
);
LOG "Starting kernel";
$poe_kernel->run();
LOG "Kernel exited";
exit 0;
sub build_is_running
{
my $exit_code = get_exit_code();
return (defined $exit_code and $exit_code == 259);
}
sub get_exit_code
{
return undef if not $build_process;
my $exit_code;
$build_process->GetExitCode($exit_code);
return $exit_code;
}
sub abort_build
{
LOG "Aborting build";
open my $f, '>', 'build_abort';
}
sub start_build
{
my %params = @_;
LOG "Starting build";
unlink 'build_abort';
$build_start_time = time;
Win32::Process::Create(
$build_process,
"c:\\perl\\bin\\perl.exe",
"perl build.pl" . ($params{commit} ? ' --commitlatest' : '') . ($params{force} ? ' --force' : ''),
0,
CREATE_NO_WINDOW,
"c:\\0ad\\autobuild") or die "Error spawning build script: ".Win32::FormatMessage(Win32::GetLastError());
$build_required = 0;
$commit_required = 0;
$build_active = 1;
}

View File

@ -1,2 +0,0 @@
aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

View File

@ -1,167 +0,0 @@
# Build script - does the actual building of the project
use strict;
use warnings;
use constant EXIT_BUILDCOMPLETE => 0;
use constant EXIT_FAILED => 1;
my %config = (load_conf("c:\\0ad\\autobuild\\aws.conf"), load_conf("d:\\0ad\\autobuild\\run.conf"));
my $build_options = do "d:\\0ad\\autobuild\\options.pl";
my $svn_trunk = "e:\\svn";
my $temp_trunk = "d:\\0ad\\svn";
my $log_dir = "d:\\0ad\\buildlogs";
my $vcbuild = "$svn_trunk\\source\\tools\\autobuild2\\vcbuild_env.bat";
my @gloox_libs = qw(glooxwrapper.dll glooxwrapper.lib glooxwrapper.pdb glooxwrapper_dbg.dll glooxwrapper_dbg.lib glooxwrapper_dbg.pdb);
my $time_start = time();
eval { # catch deaths
# Clean the output directory, just in case it's got old junk left over somehow
`rmdir /q /s $temp_trunk 2>&1`; # (ignore failures, they don't matter)
`rmdir /q /s $log_dir 2>&1`; # (ignore failures, they don't matter)
mkdir $temp_trunk or die $!;
mkdir $log_dir or die $!;
# Capture all output
open STDOUT, '>', "$log_dir\\build_stdout.txt";
open STDERR, '>', "$log_dir\\build_stderr.txt";
open BUILDLOG, '>', "$log_dir\\buildlog.txt" or die $!;
add_to_buildlog("Starting build");
chdir $svn_trunk or die $!;
# Copy all the necessary files into the temporary working area
# For some directories, do a real copy
for (qw(build source libraries))
{
add_to_buildlog("xcopying $_");
`xcopy /e $svn_trunk\\$_ $temp_trunk\\$_\\ 2>&1`;
die "xcopy $_: $?" if $?;
}
# # For other directories (which we're only going to read), do a 'junction' (like a symbolic link) because it's faster
# #
# # Actually don't, because it's easier to not have to install the junction tool
# for (qw(source libraries))
# {
# `$junction $temp_trunk\\$_ $svn_trunk\\$_`;
# die "junction $_: $?" if $?;
# }
# Store the SVN revision identifier in a file, so it can be embedded into the .exe
{
my $rev = `svnversion -n $svn_trunk`;
die "svnversion: $?" if $?;
add_to_buildlog("SVN revision $rev");
open my $f, '>', "$temp_trunk\\build\\svn_revision\\svn_revision.txt" or die $!;
print $f qq{L"$rev"\n};
}
# Create the workspace files
my $updateworkspaces_args = '';
$updateworkspaces_args .= ' --atlas' if $build_options->{atlas};
$updateworkspaces_args .= ' --collada' if $build_options->{collada};
$updateworkspaces_args .= ' --build-shared-glooxwrapper' if $build_options->{glooxwrapper};
add_to_buildlog("Running update-workspaces$updateworkspaces_args");
chdir "$temp_trunk\\build\\workspaces" or die $!;
my $updateworkspaces_output = `update-workspaces.bat$updateworkspaces_args 2>&1`;
add_to_buildlog($updateworkspaces_output);
die $? if $?;
# Create target directories for built files
mkdir "$temp_trunk\\binaries" or die $!;
mkdir "$temp_trunk\\binaries\\system" or die $!;
# Copy the prebuilt glooxwrapper, if needed
if (not $build_options->{glooxwrapper}) {
add_to_buildlog("copying glooxwrapper");
for (@gloox_libs) {
`copy $svn_trunk\\binaries\\system\\$_ $temp_trunk\\binaries\\system\\`;
die "Failed to copy $_: $?" if $?;
}
}
# Do the Release build
add_to_buildlog("Running vcbuild (release)");
my $build_output = `$vcbuild /time /M2 /logfile:$log_dir\\build_vcbuild.txt vc2008\\pyrogenesis.sln "Release|Win32" 2>&1`;
add_to_buildlog($build_output);
die $? if ($? and $? != 32768);
# Do the Debug build of glooxwrapper, if needed
if ($build_options->{glooxwrapper}) {
add_to_buildlog("Running vcbuild (debug glooxwrapper)");
my $build_output = `$vcbuild /time /M2 /logfile:$log_dir\\build_vcbuild.txt vc2008\\glooxwrapper.vcproj "Debug|Win32" 2>&1`;
add_to_buildlog($build_output);
die $? if ($? and $? != 32768);
}
# Copy the output
add_to_buildlog("Copying generated binaries");
my @binaries = qw(pyrogenesis.exe pyrogenesis.pdb);
push @binaries, 'AtlasUI.dll' if $build_options->{atlas};
push @binaries, 'Collada.dll' if $build_options->{collada};
push @binaries, @gloox_libs if $build_options->{glooxwrapper};
for (@binaries) {
`copy $temp_trunk\\binaries\\system\\$_ $svn_trunk\\binaries\\system\\`;
die "Failed to copy $_: $?" if $?;
}
# Commit to SVN
my $commit_binaries = join ' ', map "$svn_trunk\\binaries\\system\\$_", @binaries;
my $svn_output = `svn commit --username $config{svn_username} --password $config{svn_password} $commit_binaries --message "Automated build." 2>&1`;
add_to_buildlog($svn_output);
die $? if $?;
}; # end of eval
if ($@)
{
warn $@;
quit(EXIT_FAILED);
}
else
{
quit(EXIT_BUILDCOMPLETE);
}
# Exit, after copying the current log files over the previous ones
sub quit
{
my $time_end = time();
my $time_taken = $time_end - $time_start;
add_to_buildlog("Build completed with code $_[0] - took $time_taken seconds.");
exit($_[0]);
}
sub add_to_buildlog
{
print BUILDLOG +(gmtime time)."\n$_[0]\n--------------------------------------------------------------------------------\n";
}
sub load_conf {
my ($filename) = @_;
open my $f, '<', $filename or die "Failed to open $filename: $!";
my %c;
while (<$f>) {
if (/^(.+?): (.+)/) {
$c{$1} = $2;
}
}
return %c;
}

View File

@ -1,41 +0,0 @@
<!DOCTYPE html>
<title>WFG Autobuilder Logs</title>
<style>
body { font-family: sans-serif; font-size: small; }
ul { margin: 0; padding: 0; }
li { list-style: none; margin: 0; padding: 0; }
</style>
<ul id="logs">
<li>Loading...
</ul>
<script>
window.onload = function () {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
document.getElementById('logs').innerHTML = '<li>HTTP error '+xhr.status;
return;
}
var items = [];
var contents = xhr.responseXML.getElementsByTagName('Contents');
for (var i = 0; i < contents.length; ++i) {
var key = contents[i].getElementsByTagName('Key')[0].textContent;
if (key == 'logindex.html') continue;
var size = contents[i].getElementsByTagName('Size')[0].textContent;
items.push( [key, size] );
}
items.sort(function (a, b) { return a[0] < b[0] ? 1 : a[0] > b[0] ? -1 : 0 });
var output = '';
for (var i = 0; i < items.length; ++i)
output += '<li><a href="' + escape(items[i][0]) + '">' + items[i][0] + '</a> (' + items[i][1] + ' bytes)';
document.getElementById('logs').innerHTML = output;
}
}
xhr.send('');
}
</script>

View File

@ -1,352 +0,0 @@
#!/usr/bin/perl -wT
use strict;
use warnings;
use CGI::Simple;
use CGI::Carp qw(fatalsToBrowser);
use DBI;
use Net::Amazon::EC2;
use DateTime::Format::ISO8601;
use Archive::Zip;
use MIME::Base64;
use IO::String;
use Data::Dumper;
my $root = '/var/svn/autobuild';
my %config = load_conf("$root/manage.conf");
my $cgi = new CGI::Simple;
my $user = $cgi->remote_user;
die unless $user;
my $dbh = DBI->connect("dbi:SQLite:dbname=$root/$config{database}", '', '', { RaiseError => 1 });
my $ec2 = new Net::Amazon::EC2(
AWSAccessKeyId => $config{aws_access_key_id},
SecretAccessKey => $config{aws_secret_access_key},
);
my @build_options = (
{ name => 'atlas', title => 'Atlas DLL' },
{ name => 'collada', title => 'Collada DLL' },
# { name => 'glooxwrapper', title => 'Glooxwrapper DLL' }, # this requires the autobuilder to use the same VS version gloox-1.0.dll was built with
);
my $action = $cgi->url_param('action');
if (not defined $action or $action eq 'index') {
log_action('index');
print_index('');
} elsif ($action eq 'start') {
die "Must be POST" unless $cgi->request_method eq 'POST';
log_action('start');
=pod
Only one instance may run at once, and we need to prevent race conditions.
So:
* Use SQLite as a mutex, so only one CGI script can be trying to start at once
* If the last attempted start was only a few seconds ago, reject this one since
it's probably a double-click or something
* Check the list of active machines. If it's non-empty, reject this request.
* Otherwise, start the new machine.
=cut
$dbh->begin_work;
die unless 1 == $dbh->do('UPDATE state SET value = ? WHERE key = ?', undef, $$, 'process_mutex');
my ($last_start) = $dbh->selectrow_array('SELECT value FROM state WHERE key = ?', undef, 'last_start');
my $last_start_age = time() - $last_start;
die "Last start was only $last_start_age seconds ago - please try again later."
if $last_start_age < 10;
die unless 1 == $dbh->do('UPDATE state SET value = ? WHERE key = ?', undef, time(), 'last_start');
my $instances_status = get_ec2_status_table();
for (@$instances_status) {
if (instance_is_autobuild($_) and $_->{instance_state} ne 'terminated') {
die "Already got an active instance ($_->{instance_id}) - can't start another one.";
}
}
# No instances are currently active, and nobody else is in this
# instance-starting script, so it's safe to start a new one
my $instances = start_ec2_instance();
$dbh->commit;
for (@$instances) {
$dbh->do('INSERT INTO instances VALUES (?, ?)', undef, $_->{instance_id}, DateTime->now->iso8601);
}
print_index(generate_status_table($instances, 'Newly started instance') . '<hr>');
} elsif ($action eq 'stop') {
die "Must be POST" unless $cgi->request_method eq 'POST';
my $id = $cgi->url_param('instance_id');
$id =~ /\Ai-[0-9a-f]+\z/ or die "Invalid instance_id";
log_action('stop', $id);
stop_ec2_instance($id);
print_index("<strong>Stopping instance $id</strong><hr>");
} elsif ($action eq 'console') {
my $id = $cgi->url_param('instance_id');
$id =~ /\Ai-[0-9a-f]+\z/ or die "Invalid instance_id";
log_action('console', $id);
my $output = get_console_output($id);
$output =~ s/</&lt;/g;
print_index("<strong>Console output from $id:</strong><pre>\n$output</pre><hr>");
} elsif ($action eq 'activity') {
my $days = int $cgi->url_param('days') || 7;
print_activity($days);
} else {
log_action('invalid', $action);
die "Invalid action '$action'";
}
$dbh->disconnect;
sub instance_is_autobuild {
my ($instance) = @_;
return 0 if $instance->{key_name} eq 'backupserver';
return 1;
}
sub print_index {
my ($info) = @_;
my $instances_status = get_ec2_status_table();
my $got_active_instance;
for (@$instances_status) {
if (instance_is_autobuild($_) and $_->{instance_state} ne 'terminated') {
$got_active_instance = $_->{instance_id} || '?';
}
}
my $status = generate_status_table($instances_status, 'Current EC2 machine status');
print <<EOF;
Pragma: no-cache
Content-Type: text/html
<!DOCTYPE html>
<title>0 A.D. autobuild manager</title>
<link rel="stylesheet" href="manage.css">
<p>Hello <i>$user</i>.</p>
<p>
<a href="?action=index">Refresh status</a> |
<a href="http://wfg-autobuild-logs.s3.amazonaws.com/logindex.html">View build logs</a>
</p>
<hr>
$info
$status
<p>
EOF
if ($got_active_instance) {
print qq{<button disabled title="Already running an instance ($got_active_instance)">Start new build</button>\n};
} else {
print qq{<form action="?action=start" method="post" onsubmit="return confirm('Are you sure you want to start a new build?')">\n};
print qq{<fieldset><legend>Build options</legend>\n};
for (@build_options) {
print qq{<label><input type="checkbox" name="option_$_->{name}">$_->{title}</label><br>};
}
print qq{<button type="submit">Start new build</button>\n};
print qq{</fieldset></form>\n};
}
}
sub log_action {
my ($action, $params) = @_;
$dbh->do('INSERT INTO activity (user, ip, ua, action, params) VALUES (?, ?, ?, ?, ?)',
undef, $user, $cgi->remote_addr, $cgi->user_agent, $action, $params);
}
sub print_activity {
my ($days) = @_;
print <<EOF;
Content-Type: text/html
<!DOCTYPE html>
<title>0 A.D. autobuild activity log</title>
<link rel="stylesheet" href="manage.css">
<table>
<tr><th>Date<th>User<th>IP<th>Action<th>Params<th>UA
EOF
my $sth = $dbh->prepare("SELECT * FROM activity WHERE timestamp > datetime('now', ?) ORDER BY id DESC");
$sth->execute("-$days day");
while (my $row = $sth->fetchrow_hashref) {
print '<tr>';
print '<td>'.$cgi->escapeHTML($row->{$_}) for qw(timestamp user ip action params ua);
print "\n";
}
print <<EOF;
</table>
EOF
}
sub generate_status_table {
my ($instances, $caption) = @_;
my @columns = (
[ reservation_id => 'Reservation ID' ],
[ instance_id => 'Instance ID' ],
[ instance_state => 'State' ],
[ image_id => 'Image ID '],
[ dns_name => 'DNS name' ],
[ launch_time => 'Launch time' ],
[ reason => 'Last change' ],
);
my $count = @$instances;
my $status = qq{<table id="status">\n<caption>$caption &mdash; $count instances</caption>\n<tr>};
for (@columns) { $status .= qq{<th>$_->[1]}; }
$status .= qq{\n};
for my $item (@$instances) {
$status .= qq{<tr>};
for (@columns) {
my $key = $_->[0];
my $val = $item->{$key} // '';
if ($key eq 'launch_time') {
my $t = DateTime::Format::ISO8601->parse_datetime($val);
my $now = DateTime->now();
my $diff = $now - $t;
my ($days, $hours, $minutes) = $diff->in_units('days', 'hours', 'minutes');
my $age = "$minutes minutes ago";
$age = "$hours hours, $age" if $hours;
$age = "$days days, $age" if $days;
$status .= qq{<td>$val ($age)};
} else {
$status .= qq{<td>$val};
}
}
$status .= qq{<td><a href="?action=console;instance_id=$item->{instance_id}">Console output</a>\n};
$status .= qq{<td><form action="?action=stop;instance_id=$item->{instance_id}" method="post" onsubmit="return confirm('Are you sure you want to terminate this instance?')"><button type="submit">Terminate</button></form>\n}
if instance_is_autobuild($item);
}
$status .= qq{</table>};
return $status;
}
sub flatten_instance {
my ($reservation, $instance) = @_;
return {
reservation_id => $reservation->reservation_id,
instance_id => $instance->instance_id,
instance_state => $instance->instance_state->name,
image_id => $instance->image_id,
dns_name => $instance->dns_name,
launch_time => $instance->launch_time,
reason => $instance->reason,
key_name => $instance->key_name,
};
}
sub get_ec2_status_table {
# return [ ];
# return [ {
# reservation_id => 'r-12345678',
# instance_id => 'i-12345678',
# instance_state => 'pending',
# image_id => 'ami-12345678',
# dns_name => '',
# launch_time => '2008-12-30T17:14:22.000Z',
# reason => '',
# } ];
my $reservations = $ec2->describe_instances();
my @ret = ();
for my $reservation (@$reservations) {
push @ret, map flatten_instance($reservation, $_), @{$reservation->instances_set};
}
return \@ret;
}
sub get_console_output {
my ($instance_id) = @_;
my $output = $ec2->get_console_output(InstanceId => $instance_id);
return "(Last updated: ".$output->timestamp.")\n".$output->output;
}
sub start_ec2_instance {
# return [ {
# reservation_id => 'r-12345678',
# instance_id => 'i-12345678',
# instance_state => 'pending',
# image_id => 'ami-12345678',
# dns_name => '',
# launch_time => '2008-12-30T17:14:22.000Z',
# reason => '',
# } ];
my $user_data = create_user_data();
my $reservation = $ec2->run_instances(
ImageId => $config{image_id},
MinCount => 1,
MaxCount => 1,
KeyName => $config{key_name},
SecurityGroup => $config{security_group},
UserData => encode_base64($user_data),
InstanceType => $config{instance_type},
'Placement.AvailabilityZone' => $config{availability_zone},
);
if (ref $reservation eq 'Net::Amazon::EC2::Errors') {
die "run_instances failed:\n".(Dumper $reservation);
}
return [ map flatten_instance($reservation, $_), @{$reservation->instances_set} ];
}
sub create_user_data {
my @files = qw(run.pl run.conf);
my $zip = new Archive::Zip;
for (@files) {
$zip->addFile("$root/$_", "$_") or die "Failed to add $root/$_ to zip";
}
my %options;
for (@build_options) {
$options{$_->{name}} = ($cgi->param('option_'.$_->{name}) ? 1 : 0);
}
my $options = Dumper \%options;
$zip->addString($options, 'options.pl') or die "Failed to add options.pl to zip";
my $fh = new IO::String;
if ($zip->writeToFileHandle($fh) != Archive::Zip::AZ_OK) {
die "writeToFileHandle failed";
}
return ${$fh->string_ref};
}
sub stop_ec2_instance {
my ($instance_id) = @_;
# return;
$ec2->terminate_instances(
InstanceId => $instance_id,
);
}
sub load_conf {
my ($filename) = @_;
open my $f, '<', $filename or die "Failed to open $filename: $!";
my %c;
while (<$f>) {
if (/^(.+?): (.+)/) {
$c{$1} = $2;
}
}
return %c;
}

View File

@ -1,8 +0,0 @@
aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
database: manage.db
image_id: ami-XXXXXXXX
instance_type: m1.small
availability_zone: us-east-1c
key_name: XXX
security_group: XXX

View File

@ -1,11 +0,0 @@
body {
font-family: sans-serif;
}
table {
border-collapse: collapse;
}
table th, table td {
border: 1px solid #aaa;
}

View File

@ -1,21 +0,0 @@
CREATE TABLE activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
user TEXT NOT NULL,
ip TEXT NOT NULL,
ua TEXT NOT NULL,
action TEXT NOT NULL, -- like "index", "start", "stop", "console"
params TEXT -- action-dependent - typically just the instance ID
);
CREATE TABLE instances (
instance_id TEXT NOT NULL PRIMARY KEY,
local_launch_time TEXT NOT NULL
);
CREATE TABLE state (
key TEXT NOT NULL PRIMARY KEY,
value TEXT NOT NULL
);
INSERT INTO state VALUES ('process_mutex', '');
INSERT INTO state VALUES ('last_start', '0');

View File

@ -1,7 +0,0 @@
ec2_metadata_root: http://169.254.169.254/2008-09-01/meta-data/
ebs_volume_id: vol-XXXXXXXX
ebs_device: xvdg
ebs_drive_letter: e
sync: c:\bin\sync.exe
svn_username: autobuild
svn_password: XXXXXXXXX

View File

@ -1,238 +0,0 @@
=pod
This script does the EC2-specific stuff
It is responsible for:
* attaching the necessary disks,
* updating from SVN,
* executing the rest of the build script that's in SVN,
* cleaning up at the end,
* and saving the logs of everything that's going on.
i.e. everything except actually building.
=cut
use strict;
use warnings;
use Net::Amazon::EC2;
use Amazon::S3;
use LWP::Simple();
use DateTime;
# Fix clock drift, else S3 will be unhappy
system("net time /setsntp:time.windows.com");
system("w32tm /resync /rediscover");
my %config = (load_conf("c:\\0ad\\autobuild\\aws.conf"), load_conf("d:\\0ad\\autobuild\\run.conf"));
my $timestamp = DateTime->now->iso8601;
my $s3 = new Amazon::S3( {
aws_access_key_id => $config{aws_access_key_id},
aws_secret_access_key => $config{aws_secret_access_key},
retry => 1,
} );
my $bucket = $s3->bucket('wfg-autobuild-logs');
my $log = '';
$SIG{__WARN__} = sub {
write_log("Warning: @_");
warn @_;
};
write_log("Starting");
flush_log();
my $ec2;
$SIG{__DIE__} = sub {
die @_ if $^S; # ignore deaths in eval
write_log("Died\n@_");
flush_log();
if ($ec2) {
terminate_instance();
}
die @_;
};
connect_to_ec2();
my $instance_id = get_instance_id();
write_log("Running on instance $instance_id");
flush_log();
attach_disk();
update_svn();
run_build_script();
save_buildlogs();
connect_to_ec2(); # in case it timed out while building
detach_disk();
write_log("Finished");
terminate_instance();
exit;
sub update_svn {
write_log("Updating from SVN");
my $output = `svn up --username $config{svn_username} --password $config{svn_password} e:\\svn 2>&1`;
write_log("svn up:\n================================\n$output\n================================\n");
}
sub run_build_script {
write_log("Running build script");
my $output = `perl e:\\svn\\source\\tools\\autobuild2\\build.pl 2>&1`;
write_log("Build script exited with code $?:\n================================\n$output\n================================\n");
}
sub save_buildlogs {
opendir my $d, "d:\\0ad\\buildlogs" or do { write_log("Can't open buildlogs directory: $!"); return };
for my $fn (sort readdir $d) {
next if $fn =~ /^\./;
open my $f, '<', "d:\\0ad\\buildlogs\\$fn" or die "Can't open buildlogs file $fn: $!";
my $data = do { local $/; <$f> };
write_log("$fn:\n================================\n$data\n================================\n");
}
}
sub connect_to_ec2 {
# This might need to be called more than once, if you wait
# so long that the original connection times out
$ec2 = new Net::Amazon::EC2(
AWSAccessKeyId => $config{aws_access_key_id},
SecretAccessKey => $config{aws_secret_access_key},
);
}
sub attach_disk {
write_log("Attaching volume $config{ebs_volume_id} as $config{ebs_device}");
my $status = $ec2->attach_volume(
InstanceId => $instance_id,
VolumeId => $config{ebs_volume_id},
Device => $config{ebs_device},
);
write_log("Attached");
# Wait for the disk to get attached and visible
write_log("Waiting for volume to be visible");
my $mounts;
for my $i (0..60) {
# mountvol emits a list of volumes, so wait until the expected one is visible
$mounts = `mountvol`;
my $letter = uc $config{ebs_drive_letter};
if ($mounts =~ /(\\\\\?\\Volume\{\S+\}\\)\s+$letter:\\/) {
my $volume = $1;
write_log("Already got volume $volume mounted on drive $config{ebs_drive_letter}");
return;
} elsif ($mounts =~ /(\\\\\?\\Volume\{\S+\}\\)\s+\*\*\* NO MOUNT POINTS \*\*\*/) {
my $volume = $1;
write_log("Mounting volume $volume onto drive $config{ebs_drive_letter}");
system("mountvol $config{ebs_drive_letter}: $volume");
return;
}
write_log("Not seen the volume yet ($i)");
sleep 1;
}
die "Failed to find new volume. mountvol said:\n\n$mounts";
}
sub detach_disk {
# Based on http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1841&categoryID=174
write_log("Syncing drive $config{ebs_drive_letter}");
system("$config{sync} -r $config{ebs_drive_letter}:");
write_log("Unmounting drive $config{ebs_drive_letter}");
system("mountvol $config{ebs_drive_letter}: /d");
write_log("Detaching volume");
my $status = $ec2->detach_volume(
InstanceId => $instance_id,
VolumeId => $config{ebs_volume_id},
);
write_log("Detached");
}
sub terminate_instance {
write_log("Terminating instance (after a delay)");
flush_log();
# write_log("NOT REALLY");
# flush_log();
# return;
# Delay for a while, to give me a chance to log in and manually
# abort the termination if I want to configure the machine instead
# of having it die straightaway
sleep 60*5;
write_log("Really terminating now");
flush_log();
connect_to_ec2(); # in case it timed out while sleeping
while (1) {
my $statuses = $ec2->terminate_instances(
InstanceId => $instance_id,
);
# use Data::Dumper;
# write_log("Termination status $statuses -- ".(Dumper $statuses));
# flush_log();
sleep 15;
}
}
sub get_instance_id {
my $instance_id = LWP::Simple::get("$config{ec2_metadata_root}instance-id");
die "Invalid instance-id return value '$instance_id'" unless $instance_id =~ /\Ai-[a-f0-9]+\z/;
return $instance_id;
}
sub write_log {
my ($msg) = @_;
print "$msg\n";
my $t = scalar gmtime;
$log .= "$t: $msg\n\n";
# Instead of using the explicit flush_log, just flush all
# the time because it helps with debugging
flush_log_really();
}
sub flush_log_really {
my $filename = "$timestamp.startup";
my $ok = $bucket->add_key($filename, $log, {
acl_short => 'public-read',
'Content-Type' => 'text/plain',
});
warn "Failed - ".$bucket->errstr if not $ok;
}
sub flush_log {
# flush_log_really();
}
sub load_conf {
my ($filename) = @_;
open my $f, '<', $filename or die "Failed to open $filename: $!";
my %c;
while (<$f>) {
if (/^(.+?): (.+)/) {
$c{$1} = $2;
}
}
return %c;
}

View File

@ -1,43 +0,0 @@
=pod
This script is executed on startup (via a service) on the build server.
It does as little as possible, since it is necessarily frozen
into the static machine image and is hard to update.
The interesting code is passed in a zip file via the EC2 user-data API.
=cut
use strict;
use warnings;
use LWP::Simple();
use Archive::Zip;
use IO::String;
open STDOUT, '>c:/0ad/autobuild/stdout.txt';
open STDERR, '>c:/0ad/autobuild/stderr.txt';
STDOUT->autoflush;
STDERR->autoflush;
# This bit sometimes fails, for reasons I don't understand, so just keep trying it lots of times
for my $i (0..60) {
mkdir 'd:/0ad' and last;
warn "($i) $!";
sleep 1;
}
my $extract_root = 'd:/0ad/autobuild';
extract_user_data();
do "$extract_root/run.pl";
sub extract_user_data {
my $data = LWP::Simple::get('http://169.254.169.254/2008-09-01/user-data');
my $zip = Archive::Zip->new();
$zip->readFromFileHandle(new IO::String($data));
for ($zip->members) {
$_->extractToFileNamed("$extract_root/" . $_->fileName);
}
}

View File

@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "startupservice", "startupservice\startupservice.vcproj", "{BF477C43-3A77-4B56-8819-85EAC97C143D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BF477C43-3A77-4B56-8819-85EAC97C143D}.Debug|Win32.ActiveCfg = Debug|Win32
{BF477C43-3A77-4B56-8819-85EAC97C143D}.Debug|Win32.Build.0 = Debug|Win32
{BF477C43-3A77-4B56-8819-85EAC97C143D}.Release|Win32.ActiveCfg = Release|Win32
{BF477C43-3A77-4B56-8819-85EAC97C143D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,41 +0,0 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("WFG Autobuild Startup")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("")];
[assembly:AssemblyProductAttribute("startupservice")];
[assembly:AssemblyCopyrightAttribute("")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,63 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon placed first or with lowest ID value becomes application icon
LANGUAGE 9, 2
#pragma code_page(1252)
1 ICON "app.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
"\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,3 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by app.rc

View File

@ -1,264 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="startupservice"
ProjectGUID="{BF477C43-3A77-4B56-8819-85EAC97C143D}"
RootNamespace="startupservice"
Keyword="ManagedCProj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="2"
GenerateDebugInformation="true"
AssemblyDebug="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="1"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<AssemblyReference
RelativePath="System.dll"
AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.Data.dll"
AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.ServiceProcess.dll"
AssemblyName="System.ServiceProcess, Version=2.0.0.0, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.Configuration.Install.dll"
AssemblyName="System.Configuration.Install, Version=2.0.0.0, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.XML.dll"
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\AssemblyInfo.cpp"
>
</File>
<File
RelativePath=".\startupserviceWinService.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\startupserviceWinService.h"
FileType="1"
>
<File
RelativePath=".\startupserviceWinService.resX"
SubType="Designer"
>
</File>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\app.ico"
>
</File>
<File
RelativePath=".\app.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,45 +0,0 @@
// startupservice.cpp : main Windows Service project file.
#include "stdafx.h"
#include <string.h>
#include "startupserviceWinService.h"
using namespace startupservice;
using namespace System::Text;
using namespace System::Security::Policy;
using namespace System::Reflection;
//To install/uninstall the service, type: "startupservice.exe -Install [-u]"
int _tmain(int argc, _TCHAR* argv[])
{
if (argc >= 2)
{
if (argv[1][0] == _T('/'))
{
argv[1][0] = _T('-');
}
if (_tcsicmp(argv[1], _T("-Install")) == 0)
{
array<String^>^ myargs = System::Environment::GetCommandLineArgs();
array<String^>^ args = gcnew array<String^>(myargs->Length - 1);
// Set args[0] with the full path to the assembly,
Assembly^ assem = Assembly::GetExecutingAssembly();
args[0] = assem->Location;
Array::Copy(myargs, 2, args, 1, args->Length - 1);
AppDomain^ dom = AppDomain::CreateDomain(L"execDom");
Type^ type = System::Object::typeid;
String^ path = type->Assembly->Location;
StringBuilder^ sb = gcnew StringBuilder(path->Substring(0, path->LastIndexOf(L"\\")));
sb->Append(L"\\InstallUtil.exe");
Evidence^ evidence = gcnew Evidence();
dom->ExecuteAssembly(sb->ToString(), evidence, args);
}
}
else
{
ServiceBase::Run(gcnew startupserviceWinService());
}
}

View File

@ -1,83 +0,0 @@
#pragma once
using namespace System;
using namespace System::Collections;
using namespace System::ServiceProcess;
using namespace System::ComponentModel;
#include <windows.h>
namespace startupservice {
/// <summary>
/// Summary for startupserviceWinService
/// </summary>
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
public ref class startupserviceWinService : public System::ServiceProcess::ServiceBase
{
public:
startupserviceWinService()
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~startupserviceWinService()
{
if (components)
{
delete components;
}
}
/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
virtual void OnStart(array<String^>^ args) override
{
STARTUPINFO startupinfo = { 0 };
startupinfo.cb = sizeof(startupinfo);
PROCESS_INFORMATION procinfo = { 0 };
CreateProcessW(L"c:\\perl\\bin\\perl.exe", L"perl c:\\0ad\\autobuild\\startup.pl", NULL, NULL, FALSE, 0, NULL, NULL, &startupinfo, &procinfo);
}
/// <summary>
/// Stop this service.
/// </summary>
virtual void OnStop() override
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->components = gcnew System::ComponentModel::Container();
this->CanStop = true;
this->CanPauseAndContinue = true;
this->AutoLog = true;
this->ServiceName = L"startupserviceWinService";
}
#pragma endregion
};
}

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized CLR Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the CLR Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a CLR class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,5 +0,0 @@
// stdafx.cpp : source file that includes just the standard includes
// startupservice.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

View File

@ -1,11 +0,0 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here

View File

@ -1,112 +0,0 @@
#!/usr/bin/perl
=pod
To prevent runaway server instances eating up lots of money, this script
is run frequently by cron and will kill any that have been running for too long.
(The instances attempt to terminate themselves once they're finished building,
so typically this script won't be required.)
To cope with dodgy clock synchronisation, two launch times are used per instance:
the launch_time reported by EC2's describe_instances, and the local_launch_time
stored in SQLite by manage.cgi. The process is killed if either time exceeds
the cutoff limit.
=cut
use strict;
use warnings;
use DBI;
use Net::Amazon::EC2;
use DateTime::Format::ISO8601;
my $root = '/var/svn/autobuild';
my %config = load_conf("$root/manage.conf");
my $dbh = DBI->connect("dbi:SQLite:dbname=$root/$config{database}", '', '', { RaiseError => 1 });
my $now = DateTime->now;
print "\n", $now->iso8601, "\n";
# Builds should complete in <1 hour and then shut themselves off
# automatically. In case that fails, allow them to run up to 2 hours
# before forcibly terminating them, minus 20 minutes tolerance so we
# don't exceed 2 hours even if this script only runs once every ~10
# minutes.
my $cutoff = DateTime::Duration->new(minutes => 120-20);
my $ec2 = new Net::Amazon::EC2(
AWSAccessKeyId => $config{aws_access_key_id},
SecretAccessKey => $config{aws_secret_access_key},
);
my @instances;
my $reservations = $ec2->describe_instances();
for my $reservation (@$reservations) {
for my $instance (@{$reservation->instances_set}) {
my ($local_launch_time) = $dbh->selectrow_array('SELECT local_launch_time FROM instances WHERE instance_id = ?', undef, $instance->instance_id);
push @instances, {
id => $instance->instance_id,
state => $instance->instance_state->name,
launch_time => $instance->launch_time,
local_launch_time => $local_launch_time,
key_name => $instance->key_name,
};
}
}
use Data::Dumper; print Dumper \@instances;
# @instances = ( {
# id => 'i-12345678',
# state => 'pending',
# launch_time => '2008-12-30T17:14:22.000Z',
# local_launch_time => '2008-12-30T17:14:22.000Z',
# } );
for my $instance (@instances) {
next if $instance->{state} eq 'terminated';
next if $instance->{key_name} eq 'backupserver';
my $too_old = 0;
my $age = $now - DateTime::Format::ISO8601->parse_datetime($instance->{launch_time});
$too_old = 1 if DateTime::Duration->compare($age, $cutoff) > 0;
if (defined $instance->{local_launch_time}) {
my $local_age = $now - DateTime::Format::ISO8601->parse_datetime($instance->{local_launch_time});
$too_old = 1 if DateTime::Duration->compare($local_age, $cutoff) > 0;
}
next unless $too_old;
print "Terminating $instance->{id}, launched at $instance->{launch_time} / ", ($instance->{local_launch_time} || ''), "\n";
log_action('terminate', $instance->{id});
$ec2->terminate_instances(
InstanceId => $instance->{id},
);
}
$dbh->disconnect;
sub log_action {
my ($action, $params) = @_;
$dbh->do('INSERT INTO activity (user, ip, ua, action, params) VALUES (?, ?, ?, ?, ?)',
undef, 'local', '', '', $action, $params);
}
sub load_conf {
my ($filename) = @_;
open my $f, '<', $filename or die "Failed to open $filename: $!";
my %c;
while (<$f>) {
if (/^(.+?): (.+)/) {
$c{$1} = $2;
}
}
return %c;
}

View File

@ -1,2 +0,0 @@
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
vcbuild %*

View File

@ -1,132 +0,0 @@
use strict;
use warnings;
package DDS;
sub new
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $fh;
if (ref $_[0])
{
$fh = $_[0];
}
else
{
open $fh, '<', $_[0] or die "Cannot open $_[0]";
binmode $fh;
}
my %dds;
$dds{dwMagic} = pack L => read_DWORD($fh);
for (qw(Size Flags Height Width PitchOrLinearSize Depth MipMapCount))
{
$dds{"dw$_"} = read_DWORD($fh);
}
read_DWORD($fh) for 1..11; # dwReserved1
$dds{dwFlags} = expand_flags($dds{dwFlags}, 'sd');
$dds{ddpfPixelFormat} = read_DDPIXELFORMAT($fh);
$dds{ddsCaps} = read_DDCAPS2($fh);
read_DWORD($fh);# dwReserved2
bless \%dds, $class;
}
sub getType
{
my ($self) = @_;
if (grep $_ eq 'DDPF_RGB', @{$self->{ddpfPixelFormat}{dwFlags}})
{
return pack N => (
((unpack L => 'RRRR') & $self->{ddpfPixelFormat}{dwRBitMask}) |
((unpack L => 'GGGG') & $self->{ddpfPixelFormat}{dwGBitMask}) |
((unpack L => 'BBBB') & $self->{ddpfPixelFormat}{dwBBitMask}) |
((unpack L => 'AAAA') & $self->{ddpfPixelFormat}{dwRGBAlphaBitMask})
);
}
elsif (grep $_ eq 'DDPF_FOURCC', @{$self->{ddpfPixelFormat}{dwFlags}})
{
return $self->{ddpfPixelFormat}{dwFourCC}
}
else
{
die "Unknown type";
}
}
sub read_DWORD
{
die "Failed to read DWORD" unless (read $_[0], my $b, 4) == 4;
return unpack L => $b;
}
sub read_DDPIXELFORMAT
{
my $r = { map +("dw$_" => read_DWORD($_[0])),
qw(Size Flags FourCC RGBBitCount RBitMask GBitMask BBitMask RGBAlphaBitMask) };
$r->{dwFourCC} = pack L => $r->{dwFourCC};
$r->{dwFlags} = expand_flags($r->{dwFlags}, 'pf');
return $r;
}
sub read_DDCAPS2
{
my $r = { map +("dw$_" => read_DWORD($_[0])),
qw(Caps1 Caps2) };
$r->{dwCaps1} = expand_flags($r->{dwCaps1}, 'cap1');
$r->{dwCaps2} = expand_flags($r->{dwCaps2}, 'cap2');
return $r;
}
my %flag_names = (
sd => {
DDSD_CAPS => 0x00000001,
DDSD_HEIGHT => 0x00000002,
DDSD_WIDTH => 0x00000004,
DDSD_PITCH => 0x00000008,
DDSD_PIXELFORMAT => 0x00001000,
DDSD_MIPMAPCOUNT => 0x00020000,
DDSD_LINEARSIZE => 0x00080000,
DDSD_DEPTH => 0x00800000,
},
pf => {
DDPF_ALPHAPIXELS => 0x00000001,
DDPF_FOURCC => 0x00000004,
DDPF_RGB => 0x00000040,
},
cap1 => {
DDSCAPS_COMPLEX => 0x00000008,
DDSCAPS_TEXTURE => 0x00001000,
DDSCAPS_MIPMAP => 0x00400000,
},
cap2 => {
DDSCAPS2_CUBEMAP => 0x00000200,
DDSCAPS2_CUBEMAP_POSITIVEX => 0x00000400,
DDSCAPS2_CUBEMAP_NEGATIVEX => 0x00000800,
DDSCAPS2_CUBEMAP_POSITIVEY => 0x00001000,
DDSCAPS2_CUBEMAP_NEGATIVEY => 0x00002000,
DDSCAPS2_CUBEMAP_POSITIVEZ => 0x00004000,
DDSCAPS2_CUBEMAP_NEGATIVEZ => 0x00008000,
DDSCAPS2_VOLUME => 0x00200000,
},
);
sub expand_flags
{
my ($n, $name) = @_;
return [ grep $flag_names{$name}{$_} & $n, keys %{$flag_names{$name}} ];
}
1;

View File

@ -1,47 +0,0 @@
use DDS;
use Data::Dumper;
use File::Find;
my @dds;
find({
wanted => sub {
if (/(\.svn|CVS)$/)
{
$File::Find::prune = 1;
}
else
{
push @dds, $File::Find::name if /\.dds$/;
}
},
no_chdir => 1,
}, "../../../binaries/data/mods/official/art/textures/");
=pod
for my $f (@dds)
{
my $dds = new DDS($f);
print "$f\t", $dds->getType(), "\n";
}
=cut
#=pod
my @c;
for my $f (@dds)
{
my $dds = new DDS($f);
if ($dds->getType() eq 'ARGB')
{
$f =~ /(.*).dds/ or die;
push @c, $1;
}
}
print "textureconv -tga ".(join ' ', map "$_.dds", @c)."\n";
print "textureconv -abgr ".(join ' ', map "$_.tga", @c)."\n";
=cut
=pod
my $dds = new DDS("../../../binaries/data/mods/official/art/textures/ui/session/status_pane.dds");
print Dumper $dds;
=cut