diff options
author | Hans-Joachim Lankenau <hjs@openoffice.org> | 2009-10-28 14:07:42 +0100 |
---|---|---|
committer | Hans-Joachim Lankenau <hjs@openoffice.org> | 2009-10-28 14:07:42 +0100 |
commit | 38c6ee6c2cfdc60df24bd50fc7fcffd1af43807e (patch) | |
tree | 0228e82cd99c3d4e72d7989898ccea41df9c4faa /solenv/bin | |
parent | fixed broken manual merge (diff) | |
parent | Create DEV300_m62 milestone tag from trunk@277034 (diff) | |
download | core-38c6ee6c2cfdc60df24bd50fc7fcffd1af43807e.tar.gz core-38c6ee6c2cfdc60df24bd50fc7fcffd1af43807e.zip |
ause103: update to DEV300 m62
Diffstat (limited to 'solenv/bin')
-rw-r--r-- | solenv/bin/build.pl | 808 | ||||
-rw-r--r-- | solenv/bin/cws.pl | 407 | ||||
-rwxr-xr-x | solenv/bin/modules/Cws.pm | 3 | ||||
-rw-r--r-- | solenv/bin/modules/CwsConfig.pm | 92 | ||||
-rwxr-xr-x | solenv/bin/rpm-wrapper | 6 |
5 files changed, 1101 insertions, 215 deletions
diff --git a/solenv/bin/build.pl b/solenv/bin/build.pl index fba2336f8852..c351e81dd670 100644 --- a/solenv/bin/build.pl +++ b/solenv/bin/build.pl @@ -38,10 +38,14 @@ use POSIX; use Cwd qw (cwd); use File::Path; - use File::Temp qw(tmpnam); + use File::Temp qw(tmpnam tempdir); use File::Find; use Socket; use IO::Socket::INET; + use IO::Select; + use Fcntl; + use POSIX qw(:errno_h); + use Sys::Hostname; use lib ("$ENV{SOLARENV}/bin/modules"); use SourceConfig; @@ -61,6 +65,7 @@ if ($ENV{GUI} eq 'WNT' && !$cygwin) { eval { require Win32::Process; import Win32::Process; }; $enable_multiprocessing = 0 if ($@); + eval { require Win32::Pipe; import Win32::Pipe; }; }; ### for XML file format @@ -72,8 +77,7 @@ #### script id ##### ( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; - - $id_str = ' $Revision$ '; + $id_str = ' $Revision: 275224 $ '; $id_str =~ /Revision:\s+(\S+)\s+\$/ ? ($script_rev = $1) : ($script_rev = "-"); @@ -117,25 +121,25 @@ $custom_job = ''; $post_custom_job = ''; %LocalDepsHash = (); - %BuildQueue = (); %PathHash = (); %PlatformHash = (); %AliveDependencies = (); %global_deps_hash = (); # hash of dependencies of the all modules - %broken_modules_hashes = (); # hash of modules hashes, which cannot be built further + %global_deps_hash_backup = (); # backup hash of external dependencies of the all modules + %module_deps_hash_backup = (); # backup hash of internal dependencies for aech module + %modules_with_errors = (); # hash of modules hashes, which cannot be built further @broken_modules_names = (); # array of modules, which cannot be built further @dmake_args = (); %dead_parents = (); $CurrentPrj = ''; - $no_projects = 0; - $only_dependent = 0; - $build_from = ''; + $all_dependent = 1; # a flag indicating if the hash has independent keys + $build_from_with_branches = ''; $build_all_cont = ''; $build_since = ''; $dlv_switch = ''; $child = 0; %processes_hash = (); -# %module_announced = (); + %module_announced = (); $prepare = ''; # prepare for following incompatible build $ignore = ''; $html = ''; @@ -177,11 +181,15 @@ # %weight_stored = (); $grab_output = 1; $stop_build_on_error = 0; # for multiprocessing mode: do not build further module if there is an error + $interactive = 0; # for interactive mode... (for testing purpose enabled by default) + $parent_process = 1; $server_mode = 0; $setenv_string = ''; # string for configuration of the client environment $ports_string = ''; # string with possible ports for server @server_ports = (); - $socket_obj = undef; # socket object for server + $html_port; + $server_socket_obj = undef; # socket object for server + $html_socket_obj = undef; # socket object for server my %clients_jobs = (); my %clients_times = (); my $client_timeout = 0; # time for client to build (in sec)... @@ -189,12 +197,18 @@ # the server considered as an error/client crash my %lost_client_jobs = (); # hash containing lost jobs my %job_jobdir = (); # hash containing job-dir pairs + my $reschedule_queue = 0; + my %module_build_queue = (); + my %reversed_dependencies = (); my %module_paths = (); # hash with absolute module paths my %active_modules = (); my $generate_config = 0; my %add_to_config = (); my %remove_from_config = (); my $clear_config = 0; + my $finisched_children = 0; + my $debug = 0; + %module_deps_hash_pids = (); ### main ### get_options(); @@ -225,6 +239,7 @@ provide_consistency() if (defined $ENV{CWS_WORK_STAMP} && defined($ENV{COMMON_ENV_TOOLS})); $deliver_command = $ENV{DELIVER}; + $deliver_command .= ' -verbose' if ($html); $deliver_command .= ' '. $dlv_switch if ($dlv_switch); $ENV{mk_tmp}++; %prj_platform = (); @@ -255,6 +270,8 @@ }; print $new_line; + get_server_ports(); + start_interactive() if ($interactive); if ($checkparents) { GetParentDeps( $CurrentPrj, \%global_deps_hash ); @@ -422,6 +439,207 @@ sub add_modules_to_source_config { }; }; +sub start_interactive { + if ( $^O eq 'MSWin32' ) { + my $posix_sys_wait = 'POSIX ":sys_wait_h"'; + eval "use $posix_sys_wait"; + die "couldn't use $posix_sys_wait: $!\n" if ($@); + + pipe(FROM_PARENT, TO_CHILD) or die "pipe: $!"; + pipe(HTML_PIPE, TO_PARENT) or die "pipe: $!"; + + + if (my $pid = fork()) { + $html_listener_pid = 1; + close FROM_PARENT; + close TO_PARENT; + ioctl(HTML_PIPE, 0x8004667e, 1); + return; + } else { + close HTML_PIPE; + close TO_CHILD; + select TO_PARENT; + $|++; + $parent_process = 0; + start_html_listener(); + } + } else { + $pid = open(HTML_PIPE, "-|"); + print "Pipe is open\n"; + + if ($pid) { # parent + # make file handle non-bloking + my $flags = ''; + fcntl(HTML_PIPE, F_GETFL, $flags); + $flags |= O_NONBLOCK; + fcntl(HTML_PIPE, F_SETFL, $flags); + } else { # child + $parent_process = 0; + start_html_listener(); + }; + }; +}; + +sub start_html_listener { + $html_port = $server_ports[$#server_ports]; + do { + $html_port++ + } while (start_server_on_port($html_port, \$html_socket_obj)); + print "html_port:$html_port html_socket_obj: $html_socket_obj\n"; + my $new_socket_obj; + do { + $new_socket_obj = accept_html_connection(); + if (defined $new_socket_obj) { + my $html_message; + $html_message = <$new_socket_obj>; + chomp $html_message; + print $html_message . "\n"; + my $socket_message = ''; + for my $action ('rebuild', 'delete') { + if ($html_message =~ /$action=(\S+)/) { + print $new_socket_obj "Module $1 is scheduled for $action"; + }; + }; + close($new_socket_obj); + } else { + sleep(10); + }; + } while(1); +}; + +sub start_html_message_trigger { + my $child_id=fork(); ### VG: for windows there is a "simulation of the "fork"", no new procs... One can use Win32::Process::Create + + if ($child_id) { + # parent + $html_message_trigger{$child_id}++; +# print "started listener trigger\n"; + } else { + my $buffer_size = 1024; + my $buffer; + my $rv; + my $full_buffer = ''; + my %modules_to_rebuild = (); + while ($rv = sysread(HTML_PIPE, $buffer, $buffer_size)) { + $full_buffer .= $buffer; + }; + if (length $full_buffer) { + print "**********Got message $fullbuffer\n"; + socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!"; + if (connect(SOCKET, $paddr)) { + $full_buffer .= "\n"; + syswrite SOCKET, $full_buffer, length $full_buffer; +# close SOCKET or die "Child close socket: $!"; + } else { + die "Child connect: $!"; + }; + } + _exit(0); + }; +}; + +sub get_html_orders { +# print "Parent gonna read\n"; + return if (!$interactive); + my $buffer_size = 1024; + my $buffer; + my $rv; + my $full_buffer = ''; + my %modules_to_rebuild = (); + my %modules_to_delete = (); + while ($rv = sysread(HTML_PIPE, $buffer, $buffer_size)) { + $full_buffer .= $buffer; + }; +# }; + my @html_messages = split(/\n/, $full_buffer); + foreach (@html_messages) { + if (/^html_port:(\d+)/) { + $html_port = $1; + print "Html port is: $html_port\n"; + next; + };# GET /rebuild=officenames HTTP/1.0 + print "Message: $_\n"; + chomp; + if (/GET\s+\/delete=(\S+)[:(\S+)]*\s*HTTP/) { + $modules_to_delete{$1} = $2; + print "$1 scheduled for removal from build for \n"; + } + if (/GET\s+\/rebuild=(\S+)[:(\S+)]*\s*HTTP/) { + if (defined $global_deps_hash{$1}) { + print "!!! /tarModule $1 has not been built. Html order ignored\n"; + } else { + $modules_to_rebuild{$1} = $2; + print "Scheduled $1 for rebuild\n"; + } + } + }; + if (scalar keys %modules_to_delete) { + $reschedule_queue++; + schedule_delete(\%modules_to_delete); + generate_html_file(); + }; + if (scalar keys %modules_to_rebuild) { + $reschedule_queue++; + schedule_rebuild(\%modules_to_rebuild); + generate_html_file(); + }; +# print "Parent got nothing to read\n"; +}; + +sub schedule_delete { + my $modules_to_delete = shift; + foreach (keys %$modules_to_delete) { + print "Schedule module $_ for delete\n"; + delete ($global_deps_hash{$_}); + delete ($global_deps_hash_backup{$_}); + if (scalar keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}) { + kill 9, keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}; + handle_dead_children(0); + }; + RemoveFromDependencies($_, \%global_deps_hash); + RemoveFromDependencies($_, \%global_deps_hash_backup); + delete $reversed_dependencies{$_}; + delete $build_is_finished{$_} if defined $build_is_finished{$_}; + delete $modules_with_errors{$_} if defined $modules_with_errors{$_}; + delete $module_announced{$_} if defined $module_announced{$_}; + delete $html_info{$_} if defined $html_info{$_}; + delete $projects_deps_hash{$_} if defined $projects_deps_hash{$_}; + }; +}; + +sub schedule_rebuild { + my $modules_to_rebuild = shift; + foreach (keys %$modules_to_rebuild) { + if (defined $$modules_to_rebuild{$_}) { + print "Schedule directory for rebuild"; + } else { + print "Schedule complete $_ module for rebuild\n"; + if (scalar keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}) { + kill 9, keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}; + handle_dead_children(0); + }; + delete $build_is_finished{$_} if defined $build_is_finished{$_}; + delete $modules_with_errors{$_} if defined $modules_with_errors{$_}; + delete $module_announced{$_}; + initialize_html_info($_); + + foreach my $waiter (keys %{$reversed_dependencies{$_}}) { + # for rebuild_all_dependent - refacture "if" condition + ${$global_deps_hash{$waiter}}{$_}++ if (!defined $build_is_finished{$waiter}); + }; + delete $projects_deps_hash{$_} if defined $projects_deps_hash{$_}; + my %single_module_dep_hash = (); + foreach my $module (keys %{$global_deps_hash_backup{$_}}) { + if (defined ${$global_deps_hash_backup{$_}}{$module} && (!defined $build_is_finished{$module})) { + $single_module_dep_hash{$module}++; + }; + }; + $global_deps_hash{$_} = \%single_module_dep_hash; + }; + }; +}; + + # # procedure retrieves build list path # (all possibilities are taken into account) @@ -483,6 +701,42 @@ sub store_weights { }; # +# This procedure builds comlete dependency for each module, ie if the deps look like: +# mod1 -> mod2 -> mod3 -> mod4,mod5, +# than mod1 get mod3,mod4,mod5 as eplicit list of deps, not only mod2 as earlier +# +sub expand_dependencies { + my $deps_hash = shift; + + foreach my $module1 (keys %$deps_hash) { + foreach my $module2 (keys %$deps_hash) { + next if ($module1 eq $module2); + if (defined ${$$deps_hash{$module2}}{$module1}) { + ${$$deps_hash{$module2}}{$_}++ foreach (keys %{$$deps_hash{$module1}}) + }; + }; + }; +}; + +# +# This procedure fills out the %reversed_dependencies hash, +# the hash contaninig the info about modules "waiting" for the module +# +sub reverse_dependensies { + my $deps_hash = shift; + foreach my $module (keys %$deps_hash) { + foreach (keys %{$$deps_hash{$module}}) { + if (defined $reversed_dependencies{$_}) { + ${$reversed_dependencies{$_}}{$module}++ + } else { + my %single_module_dep_hash = ($module => 1); + $reversed_dependencies{$_} = \%single_module_dep_hash; + }; + }; + }; +}; + +# # Build everything that should be built # sub BuildAll { @@ -505,6 +759,9 @@ sub BuildAll { push (@warnings, "\nThere are active module in $source_config_file. Inactive modules are skipped.\n\n"); prepare_build_all_cont(\%global_deps_hash); }; + backup_deps_hash(\%global_deps_hash, \%global_deps_hash_backup); + expand_dependencies (\%global_deps_hash_backup); + reverse_dependensies(\%global_deps_hash_backup); $modules_number = scalar keys %global_deps_hash; initialize_html_info($_) foreach (keys %global_deps_hash); if ($QuantityToBuild) { @@ -514,7 +771,7 @@ sub BuildAll { if ($server_mode) { run_server(); }; - while ($Prj = PickPrjToBuild(\%global_deps_hash)) { + while ($Prj = pick_prj_to_build(\%global_deps_hash)) { if (!defined $dead_parents{$Prj}) { if (scalar keys %broken_build) { print $echo . "Skipping project $Prj because of error(s)\n"; @@ -524,7 +781,7 @@ sub BuildAll { }; $PrjDir = $module_paths{$Prj}; - get_deps_hash($Prj, \%LocalDepsHash); + get_module_dep_hash($Prj, \%LocalDepsHash); my $info_hash = $html_info{$Prj}; $$info_hash{DIRS} = check_deps_hash(\%LocalDepsHash, $Prj); $module_by_hash{\%LocalDepsHash} = $Prj; @@ -534,11 +791,10 @@ sub BuildAll { RemoveFromDependencies($Prj, \%global_deps_hash); $build_is_finished{$Prj}++; - $no_projects = 0; }; } else { store_build_list_content($CurrentPrj); - get_deps_hash($CurrentPrj, \%LocalDepsHash); + get_module_dep_hash($CurrentPrj, \%LocalDepsHash); initialize_html_info($CurrentPrj); my $info_hash = $html_info{$CurrentPrj}; $$info_hash{DIRS} = check_deps_hash(\%LocalDepsHash, $CurrentPrj); @@ -551,6 +807,15 @@ sub BuildAll { }; }; +sub backup_deps_hash { + my $source_hash = shift; + my $backup_hash = shift; + foreach $key (keys %$source_hash) { + my %values_hash = %{$$source_hash{$key}}; + $$backup_hash{$key} = \%values_hash; + }; +}; + sub initialize_html_info { my $module = shift; return if (defined $dead_parents{$module}); @@ -568,7 +833,8 @@ sub dmake_dir { my $BuildDir = shift; $jobs_hash{$BuildDir}->{START_TIME} = time(); $jobs_hash{$BuildDir}->{STATUS} = 'building'; - if ($BuildDir =~ /(\s)/o) { + if ($BuildDir =~ /(\s)/o && (!-d $BuildDir)) { + print "\n$BuildDir\n\n" if ($BuildDir =~ /\sdeliver$/o); $error_code = do_custom_job($BuildDir, \%LocalDepsHash); } else { html_store_job_info(\%LocalDepsHash, $BuildDir); @@ -713,6 +979,20 @@ sub get_deps_from_object { }; }; +# +# this function wraps the get_module_dep_hash and backups the resultung hash +# +sub get_module_dep_hash { + my ($module, $module_dep_hash) = @_; + if (defined $module_deps_hash_backup{$module}) { + backup_deps_hash($module_deps_hash_backup{$module}, $module_dep_hash); + } else { + get_deps_hash($module, $module_dep_hash); + my %values_hash = (); + backup_deps_hash($module_dep_hash, \%values_hash); + $module_deps_hash_backup{$module} = \%values_hash; + } +}; # # Getting hashes of all internal dependencies and additional @@ -739,7 +1019,7 @@ sub get_deps_hash { }; my $build_list_ref = $build_lists_hash{$module_to_build}; - delete $build_lists_hash{$module_to_build}; +# delete $build_lists_hash{$module_to_build}; if (ref($build_list_ref) eq 'XMLBuildListParser') { get_deps_from_object($module_to_build, $build_list_ref, $dependencies_hash); } else { @@ -777,12 +1057,11 @@ sub get_deps_hash { print_error("$module_to_build/prj/build.lst has wrongly written dependencies string:\n$_\n") if (!$Dependencies); $deps_hash{$_}++ foreach (GetDependenciesArray($Dependencies)); $$dependencies_hash{$DirAlias} = \%deps_hash; - $BuildQueue{$DirAlias}++; my $local_dir = ''; if ($Dir =~ /(\\|\/)/o) { - $local_dir = $'; + $local_dir = "/$'"; }; - $PathHash{$DirAlias} = CorrectPath($module_paths{$module_to_build} . "/$local_dir"); + $PathHash{$DirAlias} = CorrectPath($module_paths{$module_to_build} . $local_dir); } elsif ($_ !~ /^\s*$/ && $_ !~ /^\w*\s/o) { chomp; push(@errors, $_); @@ -967,12 +1246,14 @@ sub get_stand_dir { # # Picks project which can be built now from hash and then deletes it from hash # -sub PickPrjToBuild { +sub pick_prj_to_build { my $DepsHash = shift; - handle_dead_children(0) if ($QuantityToBuild); - my $Prj = FindIndepPrj($DepsHash); - delete $$DepsHash{$Prj}; - generate_html_file(); + get_html_orders(); + my $Prj = find_indep_prj($DepsHash); + if ($Prj) { + delete $$DepsHash{$Prj}; + generate_html_file(); + }; return $Prj; }; @@ -1015,12 +1296,9 @@ sub check_deps_hash { my @possible_order; my $module_path = $module_paths{$module} if (defined $module); return if (!scalar keys %$deps_hash_ref); - my %deps_hash = %$deps_hash_ref; + my %deps_hash = (); my $consistent; - foreach $key (keys %$deps_hash_ref) { - my %values_hash = %{$$deps_hash_ref{$key}}; - $deps_hash{$key} = \%values_hash; - }; + backup_deps_hash($deps_hash_ref, \%deps_hash); my $string; my $log_name; my $build_number = 0; @@ -1094,39 +1372,50 @@ sub check_deps_hash { # # Find project with no dependencies left. # -sub FindIndepPrj { - my ($Prj, @Prjs, $Dependencies, $i); +sub find_indep_prj { + my ($Dependencies, $i); my @candidates = (); + $all_dependent = 1; + handle_dead_children(0) if ($QuantityToBuild); my $children = children_number(); return '' if (!$server_mode && $children && ($children >= $QuantityToBuild)); $Dependencies = shift; - @Prjs = keys %$Dependencies; - if ($#Prjs != -1) { - foreach $Prj (@Prjs) { - next if (&IsHashNative($Prj)); - my $PrjDeps = $$Dependencies{$Prj}; - push(@candidates, $Prj) if (!scalar keys %$PrjDeps); + if (scalar keys %$Dependencies) { + foreach my $job (keys %$Dependencies) { + push(@candidates, $job) if (!scalar keys %{$$Dependencies{$job}}); }; if (scalar @candidates) { + $all_dependent = 0; my $best_candidate = undef; - my $weight = 0; - foreach my $candidate (sort @candidates) { - if (defined $weights_hash{$candidate} && $weights_hash{$candidate} > $weight) { - $best_candidate = $candidate; - $weight = $weights_hash{$candidate}; + my $best_weight = 0; + if (scalar @candidates > 1) { + foreach my $candidate (@candidates) { + my $candidate_weight = get_waiters_number($candidate); + if ($candidate_weight > $best_weight) { + $best_candidate = $candidate; + $best_weight = $candidate_weight; + }; }; - }; - if (defined $best_candidate) { - return $best_candidate; + if (defined $best_candidate) { + return $best_candidate; + } } my @sorted_candidates = sort(@candidates); return $sorted_candidates[0]; }; - return ''; - } else { - $no_projects = 1; - return ''; }; + return ''; +}; + +sub get_waiters_number { + my $module = shift; + if (defined $weights_hash{$module}) { + return $weights_hash{$module}; + }; + if (defined $reversed_dependencies{$module}) { + return scalar keys %{$reversed_dependencies{$module}}; + }; + return 0; }; # @@ -1206,7 +1495,7 @@ sub print_error { sub usage { print STDERR "\nbuild\n"; - print STDERR "Syntax: build [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches|-b]|[--prepare|-p][:platform] [--dontchekoutmissingmodules]] [--deliver|-d [--dlv_switch deliver_switch]]] [-P processes|--server [--setenvstring \"string\"] [--client_timeout MIN] [--port port1[:port2:...:portN]]] [--show|-s] [--help|-h] [--file|-F] [--ignore|-i] [--version|-V] [--mode|-m OOo[,SO[,EXT]] [--html [--html_path html_file_path] [--dontgraboutput]] [--pre_job=pre_job_sring] [--job=job_string|-j] [--post_job=post_job_sring] [--stoponerror] [--genconf [--removeall|--clear|--remove|--add module1,module2[,...,moduleN]]]\n"; + print STDERR "Syntax: build [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches|-b]|[--prepare|-p][:platform] [--deliver|-d [--dlv_switch deliver_switch]]] [-P processes|--server [--setenvstring \"string\"] [--client_timeout MIN] [--port port1[:port2:...:portN]]] [--show|-s] [--help|-h] [--file|-F] [--ignore|-i] [--version|-V] [--mode|-m OOo[,SO[,EXT]] [--html [--html_path html_file_path] [--dontgraboutput]] [--pre_job=pre_job_sring] [--job=job_string|-j] [--post_job=post_job_sring] [--stoponerror] [--genconf [--removeall|--clear|--remove|--add module1,module2[,...,moduleN]]] [--interactive]\n"; print STDERR "Example1: build --from sfx2\n"; print STDERR " - build all projects dependent from sfx2, starting with sfx2, finishing with the current module\n"; print STDERR "Example2: build --all:sfx2\n"; @@ -1246,7 +1535,7 @@ sub usage { print STDERR " --removeall|--clear - remove all active modules(s) from configuration file\n"; print STDERR " --stoponerror - stop build when error occurs (for mp builds)\n"; - print STDERR " --dontchekoutmissingmodules - do not chekout missing modules when running prepare (links still will be broken)\n"; + print STDERR " --interactive - start interactive build process (process can be managed via html page)\n"; print STDERR " Custom jobs:\n"; print STDERR " --job=job_string - execute custom job in (each) module. job_string is a shell script/command to be executed instead of regular dmake jobs\n"; print STDERR " --pre_job=pre_job_string - execute preliminary job in (each) module. pre_job_string is a shell script/command to be executed before regular job in the module\n"; @@ -1278,9 +1567,9 @@ sub get_options { $arg =~ /^-F$/ and $cmd_file = shift @ARGV and next; $arg =~ /^--with_branches$/ and $BuildAllParents = 1 - and $build_from = shift @ARGV and next; + and $build_from_with_branches = shift @ARGV and next; $arg =~ /^-b$/ and $BuildAllParents = 1 - and $build_from = shift @ARGV and next; + and $build_from_with_branches = shift @ARGV and next; $arg =~ /^--all:(\S+)$/ and $BuildAllParents = 1 and $build_all_cont = $1 and next; @@ -1327,6 +1616,7 @@ sub get_options { $arg =~ /^-m$/ and get_modes() and next; $arg =~ /^--mode$/ and get_modes() and next; $arg =~ /^--stoponerror$/ and $stop_build_on_error = 1 and next; + $arg =~ /^--interactive$/ and $interactive = 1 and next; if ($arg =~ /^--$/) { push (@dmake_args, get_dmake_args()) if (!$custom_job); next; @@ -1338,9 +1628,9 @@ sub get_options { print_error("\"--dontgraboutput\" switch is used only with \"--html\"") if ($dont_grab_output); }; $grab_output = 0 if ($dont_grab_output); - print_error('Switches --with_branches and --all collision') if ($build_from && $build_all_cont); + print_error('Switches --with_branches and --all collision') if ($build_from_with_branches && $build_all_cont); # print_error('Please prepare the workspace on one of UNIX platforms') if ($prepare && ($ENV{GUI} ne 'UNX')); - print_error('Switches --with_branches and --since collision') if ($build_from && $build_since); + print_error('Switches --with_branches and --since collision') if ($build_from_with_branches && $build_since); if ($show) { $QuantityToBuild = 0; $cmd_file = ''; @@ -1363,7 +1653,7 @@ sub get_options { print_error("Switches -P and --server collision"); }; } elsif ($stop_build_on_error) { - print_error("Switche --stoponerror is only for multiprocessing builds"); + print_error("Switch --stoponerror is only for multiprocessing builds"); }; if ($server_mode) { $html++; @@ -1388,6 +1678,11 @@ sub get_options { $only_common = 'common'; $only_common .= '.pro' if ($only_platform =~ /\.pro$/); }; + if ($interactive) { + $html++; # enable html page generation... + $local_host_name = hostname(); + $local_host_ip = inet_ntoa(scalar(gethostbyname($local_host_name)) || 'localhost'); + } # Default build modes(for OpenOffice.org) $ENV{BUILD_TYPE} = 'OOo EXT' if (!defined $ENV{BUILD_TYPE}); @ARGV = @dmake_args; @@ -1474,7 +1769,7 @@ sub cancel_build { }; # -# Function for storing error in multiprocessing AllParents build +# Function for storing errors in multiprocessing AllParents build # sub store_error { my ($pid, $error_code) = @_; @@ -1486,7 +1781,7 @@ sub store_error { return 1; }; }; - $broken_modules_hashes{$folders_hashes{$child_nick}}++; + $modules_with_errors{$folders_hashes{$child_nick}}++; $broken_build{$child_nick} = $error_code; if ($stop_build_on_error) { clear_from_child($pid); @@ -1539,6 +1834,7 @@ sub handle_dead_children { } else { clear_from_child($pid); }; + $finisched_children++; }; }; } while(children_number() >= $QuantityToBuild); @@ -1564,11 +1860,13 @@ sub clear_from_child { RemoveFromDependencies($child_nick, $folders_hashes{$child_nick}); }; + foreach (keys %module_deps_hash_pids) { + delete ${$module_deps_hash_pids{$_}}{$pid} if defined (${$module_deps_hash_pids{$_}}{$pid}); + }; my $module = $module_by_hash{$folders_hashes{$child_nick}}; html_store_job_info($folders_hashes{$child_nick}, $child_nick, $error_code); $running_children{$folders_hashes{$child_nick}}--; delete $processes_hash{$pid}; - $only_dependent = 0; print 'Running processes: ' . children_number() . "\n"; }; @@ -1580,32 +1878,28 @@ sub BuildDependent { my $pid = 0; my $child_nick = ''; $running_children{$dependencies_hash} = 0 if (!defined $running_children{$dependencies_hash}); - while ($child_nick = PickPrjToBuild($dependencies_hash)) { - if (($QuantityToBuild)) { # multiprocessing not for $BuildAllParents (-all etc)!! + while ($child_nick = pick_prj_to_build($dependencies_hash)) { + if ($QuantityToBuild) { do { - handle_dead_children(0); - if (defined $broken_modules_hashes{$dependencies_hash} && !$ignore) { - return if ($BuildAllParents); + if (defined $modules_with_errors{$dependencies_hash} && !$ignore) { + return 0 if ($BuildAllParents); last; }; # start current child & all # that could be started now start_child($child_nick, $dependencies_hash) if ($child_nick); - $child_nick = PickPrjToBuild($dependencies_hash); - if (!$child_nick) { - return if ($BuildAllParents); - handle_dead_children(1) if (!$no_projects); - }; - } while (!$no_projects); - return if ($BuildAllParents); + return 1 if ($BuildAllParents); + $child_nick = pick_prj_to_build($dependencies_hash); + } while (scalar keys %$dependencies_hash || $child_nick); while (children_number()) { +# print "#### 1902: Starting waiting for dead child\n"; handle_dead_children(1); }; # if (defined $last_module) { # $build_is_finished{$last_module}++ if (!defined $modules_with_errors{$last_module}); # }; - if (defined $broken_modules_hashes{$dependencies_hash}) { + if (defined $modules_with_errors{$dependencies_hash}) { cancel_build(); } mp_success_exit(); @@ -1626,44 +1920,41 @@ sub start_child { $jobs_hash{$job_dir}->{STATUS} = 'building'; if ($job_dir =~ /(\s)/o) { my $error_code = undef; - $error_code = do_custom_job($job_dir, $dependencies_hash); - return; + if ($job_dir !~ /\sdeliver$/o) { + $error_code = do_custom_job($job_dir, $dependencies_hash); + return; + } }; + $build_in_progress{$module_by_hash{$dependencies_hash}}++; html_store_job_info($dependencies_hash, $job_dir); my $pid = undef; my $children_running; my $oldfh = select STDOUT; $| = 1; - if ($ENV{GUI} eq 'WNT' && !$cygwin) { - print "$job_dir\n"; - my $process_obj = undef; - my $rc = Win32::Process::Create($process_obj, $dmake_bin, - $dmake_args, - 0, 0, #NORMAL_PRIORITY_CLASS, - $job_dir); -# my $rc = Win32::Process::Create($process_obj, $_4nt_exe, -# "/c $dmake_batch", -# 0, NORMAL_PRIORITY_CLASS, -# $job_dir); - print_error("Cannot start child process") if (!$rc); - $pid = $process_obj->GetProcessID(); - $windows_procs{$pid} = $process_obj; - } else { - if ($pid = fork) { # parent - } elsif (defined $pid) { # child - select $oldfh; - $child = 1; - dmake_dir($job_dir); - do_exit(1); - }; - }; - select $oldfh; - $processes_hash{$pid} = $job_dir; - $children_running = children_number(); - print 'Running processes: ', $children_running, "\n"; - $maximal_processes = $children_running if ($children_running > $maximal_processes); - $folders_hashes{$job_dir} = $dependencies_hash; - $running_children{$dependencies_hash}++; + if ($pid = fork) { # parent + select $oldfh; + $processes_hash{$pid} = $job_dir; + $children_running = children_number(); + print 'Running processes: ', $children_running, "\n"; + $maximal_processes = $children_running if ($children_running > $maximal_processes); + $folders_hashes{$job_dir} = $dependencies_hash; + store_pid($dependencies_hash, $pid); + $running_children{$dependencies_hash}++; + } elsif (defined $pid) { # child + select $oldfh; + $child = 1; + dmake_dir($job_dir); + do_exit(1); + }; +}; + +sub store_pid { + my ($deps_hash, $pid) = @_; + if (!defined $module_deps_hash_pids{$deps_hash}) { + my %module_hash_pids = (); + $module_deps_hash_pids{$deps_hash} = \%module_hash_pids; + }; + ${$module_deps_hash_pids{$deps_hash}}{$pid}++; }; # @@ -1671,26 +1962,33 @@ sub start_child { # sub build_multiprocessing { my $Prj; - my @build_queue = (); # array, containing queue of projects - # to build do { - while ($Prj = PickPrjToBuild(\%global_deps_hash)) { - push @build_queue, $Prj; - $projects_deps_hash{$Prj} = {}; - get_deps_hash($Prj, $projects_deps_hash{$Prj}); - my $info_hash = $html_info{$Prj}; - $$info_hash{DIRS} = check_deps_hash($projects_deps_hash{$Prj}, $Prj); - $module_by_hash{$projects_deps_hash{$Prj}} = $Prj; - }; - if (!$Prj || !defined $projects_deps_hash{$Prj}) { - cancel_build() if (!scalar @build_queue && !children_number()); - handle_dead_children(1); - } - build_actual_queue(\@build_queue); - } while (scalar (keys %global_deps_hash)); + my $got_module = 0; + $finisched_children = 0; + while ($Prj = pick_prj_to_build(\%global_deps_hash)) { + if (!defined $projects_deps_hash{$Prj}) { + $projects_deps_hash{$Prj} = {}; + get_module_dep_hash($Prj, $projects_deps_hash{$Prj}); + my $info_hash = $html_info{$Prj}; + $$info_hash{DIRS} = check_deps_hash($projects_deps_hash{$Prj}, $Prj); + $module_by_hash{$projects_deps_hash{$Prj}} = $Prj; + } + $module_build_queue{$Prj}++; + $got_module++; + }; + if (!$got_module) { + cancel_build() if ((!scalar keys %module_build_queue) && !children_number()); + if (!$finisched_children) { +# print "#### 1979: Starting waiting for dead child\n"; + handle_dead_children(1); + }; + }; + build_actual_queue(\%module_build_queue); + } while (scalar keys %global_deps_hash); # Let the last module be built till the end - while (scalar @build_queue) { - build_actual_queue(\@build_queue); + while (scalar keys %module_build_queue) { + build_actual_queue(\%module_build_queue); +# print "#### 1988: Starting waiting for dead child\n"; handle_dead_children(1); }; # Let all children finish their work @@ -1716,33 +2014,50 @@ sub mp_success_exit { # sub build_actual_queue { my $build_queue = shift; - my $i = 0; + my $finished_projects = 0; do { - while ($i <= (scalar(@$build_queue) - 1)) { - $Prj = $$build_queue[$i]; - if (defined $broken_modules_hashes{$projects_deps_hash{$Prj}} && !$ignore) { + my @sorted_queue = sort {(scalar keys %{$projects_deps_hash{$a}}) <=> (scalar keys %{$projects_deps_hash{$b}})} keys %$build_queue; + my $started_children = 0; +# foreach $Prj (@sorted_queue) { + foreach $Prj (keys %$build_queue) { + get_html_orders(); + if ($reschedule_queue) { + $reschedule_queue = 0; + foreach (keys %$build_queue) { + # Remove the module from the build queue if there is a dependency emerged + if ((defined $global_deps_hash{$_}) && (scalar keys %{$global_deps_hash{$_}})) { + delete $$build_queue{$_}; + }; + delete $$build_queue{$_} if (!defined $global_deps_hash_backup{$_}) + }; + return; + }; + if (defined $modules_with_errors{$projects_deps_hash{$Prj}} && !$ignore) { push (@broken_modules_names, $Prj); - splice (@$build_queue, $i, 1); + delete $$build_queue{$Prj}; next; }; - $only_dependent = 0; - $no_projects = 0; - BuildDependent($projects_deps_hash{$Prj}); - handle_dead_children(0); - if ($no_projects && + $started_children =+ BuildDependent($projects_deps_hash{$Prj}); + if ((!scalar keys %{$projects_deps_hash{$Prj}}) && !$running_children{$projects_deps_hash{$Prj}}) { - if (!defined $broken_modules_hashes{$projects_deps_hash{$Prj}} || $ignore) + if (!defined $modules_with_errors{$projects_deps_hash{$Prj}} || $ignore) { RemoveFromDependencies($Prj, \%global_deps_hash); $build_is_finished{$Prj}++; - splice (@$build_queue, $i, 1); - next; + delete $$build_queue{$Prj}; + $finished_projects++; }; }; - $i++; }; - $i = 0; - } while (!are_all_dependent($build_queue)); + # trigger wait + if (!$started_children) { + if ($finished_projects) { + return; + } else { + handle_dead_children(1); + }; + }; + } while (scalar keys %$build_queue); }; sub run_job { @@ -1793,7 +2108,7 @@ sub do_custom_job { }; }; if ($error_code) { - $broken_modules_hashes{$dependencies_hash}++; + $modules_with_errors{$dependencies_hash}++; $broken_build{$module} = $error_code; } else { RemoveFromDependencies($module_job, $dependencies_hash); @@ -1814,6 +2129,7 @@ sub announce_module { sub print_announce { my $Prj = shift; + return if (defined $module_announced{$Prj}); my $prj_type = ''; $prj_type = $modules_types{$Prj} if (defined $modules_types{$Prj}); my $text; @@ -1825,7 +2141,6 @@ sub print_announce { }; $build_is_finished{$Prj}++; } elsif ($prj_type eq 'img') { -# return if (defined $module_announced{$`}); $text = "Skipping incomplete $Prj\n"; $build_is_finished{$Prj}++; } elsif ($custom_job) { @@ -1833,17 +2148,24 @@ sub print_announce { } else { $text = "Building module $Prj\n"; }; - print $echo . "=============\n"; - print $echo . $text; + my $announce_string = $new_line; + $announce_string .= $echo . "=============\n"; + $announce_string .= $echo . $text; + $announce_string .= $echo . "=============\n"; + print $announce_string; + $module_announced{$Prj}++; }; sub are_all_dependent { my $build_queue = shift; my $folder = ''; - foreach my $prj (@$build_queue) { - $folder = FindIndepPrj($projects_deps_hash{$prj}); - return '' if ($folder); + my $first_candidate = undef; + foreach my $prj (keys %$build_queue) { + $folder = find_indep_prj($projects_deps_hash{$prj}); + $first_candidate = $folder if (!defined $first_candidate); }; + $folder = $first_candidate; + return '' if ($first_candidate); return '1'; }; @@ -1878,10 +2200,10 @@ sub modules_classify { # sub provide_consistency { check_dir(); - foreach my $module_ref (\$build_from, \$build_all_cont, \$build_since) { - if ($$module_ref) { - return if (defined $module_paths{$$module_ref}); - print_error("Cannot find module '$$module_ref'", 9); + foreach $var_ref (\$build_from_with_branches, \$build_all_cont, \$build_since) { + if ($$var_ref) { + return if (defined $module_paths{$$var_ref}); + print_error("Cannot find module '$$var_ref'", 9); return; }; }; @@ -1988,14 +2310,11 @@ sub get_tmp_dir { } else { $tmp_dir = '/tmp/'; } - - return File::Temp::tempdir(DIR =>$tmp_dir); - -# $tmp_dir .= $$ while (-e $tmp_dir); -# $tmp_dir = CorrectPath($tmp_dir); -# eval {mkpath($tmp_dir)}; -# print_error("Cannot create temporary directory in $tmp_dir") if ($@); -# return $tmp_dir; + $tmp_dir = tempdir ( DIR => $tmp_dir ); + if (!-d $tmp_dir) { + print_error("Cannot create temporary directory for checkout in $tmp_dir") if ($@); + }; + return $tmp_dir; }; @@ -2052,7 +2371,7 @@ sub prepare_incompatible_build { $incompatibles{$incomp_prj} = $$deps_hash{$incomp_prj}; delete $$deps_hash{$incomp_prj}; } - while ($prj = PickPrjToBuild($deps_hash)) { + while ($prj = pick_prj_to_build($deps_hash)) { RemoveFromDependencies($prj, $deps_hash); RemoveFromDependencies($prj, \%incompatibles); }; @@ -2112,7 +2431,7 @@ sub prepare_build_from { my ($prj, $deps_hash); $deps_hash = shift; my %from_deps_hash = (); # hash of dependencies of the -from project - GetParentDeps($build_from, \%from_deps_hash); + GetParentDeps($build_from_with_branches, \%from_deps_hash); foreach $prj (keys %from_deps_hash) { delete $$deps_hash{$prj}; RemoveFromDependencies($prj, $deps_hash); @@ -2128,7 +2447,7 @@ sub prepare_build_all_cont { $deps_hash = shift; $border_prj = $build_all_cont if ($build_all_cont); $border_prj = $build_since if ($build_since); - while ($prj = PickPrjToBuild($deps_hash)) { + while ($prj = pick_prj_to_build($deps_hash)) { $orig_prj = ''; $orig_prj = $` if ($prj =~ /\.lnk$/o); $orig_prj = $` if ($prj =~ /\.link$/o); @@ -2195,7 +2514,7 @@ sub get_incomp_projects { } else { if ($option =~ /(:)/) { $option = $`; - print_error("-from switch collision") if ($build_all_cont); + print_error("\'--from\' switch collision") if ($build_all_cont); $build_all_cont = $'; }; $incompatibles{$option}++; @@ -2255,7 +2574,7 @@ sub clear_delivered { print "$message\n"; foreach my $platform (keys %platforms) { - print "\nRemoving delivered for $platform\n"; + print "\nRemoving files delivered for $platform\n"; my %solar_vars = (); read_ssolar_vars($platform, \%solar_vars); if (scalar keys %solar_vars) { @@ -2269,7 +2588,7 @@ sub clear_delivered { my $undeliver = "$deliver_command $deliver_delete_switches $nul"; # my $current_dir = getcwd(); foreach my $module (sort @modules_built) { - if (chdir($module_paths{$module})) { + if (!chdir($module_paths{$module})) { push(@warnings, "Could not remove delivered files from the module $module. Your build can become inconsistent.\n"); } else { print "Removing delivered from module $module\n"; @@ -2442,7 +2761,8 @@ sub do_exit { # perl 5.10 returns 'resource busy' for rmtree rmdir(CorrectPath($tmp_dir)) if ($tmp_dir); } - rmtree(CorrectPath($tmp_dir), 1, 0) if ($tmp_dir); + rmtree(CorrectPath($tmp_dir), 0, 0) if ($tmp_dir); + print STDERR "Cannot delete $tmp_dir. Please remove it manually\n" if (-d $tmp_dir); exit($exit_code); }; @@ -2465,7 +2785,7 @@ sub sort_modules_appearance { delete $build_in_progress_shown{$_} if (defined $build_in_progress_shown{$_}); }; $build_in_progress_shown{$_}++ foreach (keys %build_in_progress); - push(@modules_order, $_) foreach (sort keys %build_in_progress_shown); + push(@modules_order, $_) foreach (sort { $build_in_progress_shown{$b} <=> $build_in_progress_shown{$a} } keys %build_in_progress_shown); push(@modules_order, $_) foreach (sort keys %build_is_finished); foreach(sort keys %html_info) { next if (defined $build_is_finished{$_} || defined $build_in_progress{$_} || defined $modules_with_errors{$_}); @@ -2477,6 +2797,7 @@ sub sort_modules_appearance { sub generate_html_file { return if (!$html); my $force_update = shift; + $force_update++ if ($debug); $html_last_updated = time; my @modules_order = sort_modules_appearance(); my ($successes_percent, $errors_percent) = get_progress_percentage(scalar keys %html_info, scalar keys %build_is_finished, scalar keys %modules_with_errors); @@ -2492,13 +2813,20 @@ sub generate_html_file { print HTML 'initFrames();' . "\n"; print HTML 'var IntervalID;' . "\n"; print HTML 'function loadFrame_0() {' . "\n"; - print HTML 'document.write("<html>");' . "\n"; - print HTML 'document.write("<head>");' . "\n"; - print HTML 'document.write("</head>");' . "\n"; - print HTML 'document.write("<body>");' . "\n"; + print HTML ' document.write("<html>");' . "\n"; + print HTML ' document.write("<head>");' . "\n"; + print HTML ' document.write("</head>");' . "\n"; + print HTML ' document.write("<body>");' . "\n"; if ($build_finished) { print HTML 'document.write("<h3 align=center style=\"color:red\">Build process is finished</h3>");' . "\n"; print HTML ' top.frames[0].clearInterval(top.frames[0].IntervalID);' . "\n"; + } elsif ($interactive) { + print HTML 'document.write(" <div id=divContext style=\"border: 1px solid; display: none; position: absolute\">");' . "\n"; + print HTML 'document.write(" <ul style=\"margin: 0; padding: 0.3em; list-style-type: none; background-color: lightgrey;\" :li:hover {} :hr {border: 0; border-bottom: 1px solid grey; margin: 3px 0px 3px 0px; width: 10em;} :a {border: 0 !important;} >");' . "\n"; + print HTML 'document.write(" <li><a onmouseover=\"this.style.color=\'red\'\" onmouseout=\"this.style.color=\'black\'\" id=aRebuild href=\"#\">Rebuild module</a></li>");' . "\n"; + print HTML 'document.write(" <li><a onmouseover=\"this.style.color=\'red\'\" onmouseout=\"this.style.color=\'black\'\" id=aDelete href=\"#\" >Remove module</a></li>");' . "\n"; + print HTML 'document.write(" </ul>");' . "\n"; + print HTML 'document.write(" </div>");' . "\n"; }; if ($BuildAllParents) { print HTML 'document.write("<table valign=top cellpadding=0 hspace=0 vspace=0 cellspacing=0 border=0>");' . "\n"; @@ -2556,7 +2884,12 @@ sub generate_html_file { print HTML $errors_number; print HTML ' error(s)\">', $_, '</a>");' . "\n"; } else { - print HTML 'document.write("<em style=color:gray>' . $_ . '</em>");'; +# print HTML 'document.write("<em style=color:gray>' . $_ . '</em>");'; +#### print HTML 'document.write("<em style=color:gray>' . $_ ."href=\'http://$local_host_ip:$html_port/delete=\'$_". '</em>");'; + + print HTML 'document.write(" <a target=\'infoframe\' id='; + print HTML $_; + print HTML ' href=\"javascript:void(0)\"; title=\"Remove module\">' . $_ . '</a>");' . "\n"; }; @@ -2583,13 +2916,64 @@ sub generate_html_file { print HTML 'document.write(" </tr>");' . "\n"; # </one module> } - print HTML 'document.write("</table>");' . "\n"; - print HTML 'document.write("</body>");' . "\n"; + print HTML 'document.write(" </table>");' . "\n"; + print HTML 'document.write(" </body>");' . "\n"; print HTML 'document.write("</html>");' . "\n"; print HTML 'document.close();' . "\n"; print HTML 'refreshInfoFrames();' . "\n"; print HTML '}' . "\n"; + + if (!$build_finished && $interactive ) { + print HTML 'var _replaceContext = false;' . "\n"; + print HTML 'var _mouseOverContext = false;' . "\n"; + print HTML 'var _noContext = false;' . "\n"; + print HTML 'var _divContext = $(\'divContext\');' . "\n"; + print HTML 'var activeElement = 0;' . "\n"; + print HTML 'function $(id) {return document.getElementById(id);}' . "\n"; + print HTML 'InitContext();' . "\n"; + print HTML 'function InitContext()' . "\n"; + print HTML '{' . "\n"; + print HTML ' $(\'aRebuild\').target = \'infoframe\';' . "\n"; + print HTML ' $(\'aDelete\').target = \'infoframe\';' . "\n"; + print HTML ' $(\'aRebuild\').style.color = \'black\';' . "\n"; + print HTML ' $(\'aDelete\').style.color = \'black\';' . "\n"; + print HTML ' _divContext.onmouseover = function() { _mouseOverContext = true; };' . "\n"; + print HTML ' _divContext.onmouseout = function() { _mouseOverContext = false; };' . "\n"; + print HTML ' _divContext.onclick = function() { _divContext.style.display = \'none\'; };' . "\n"; + print HTML ' document.body.onmousedown = ContextMouseDown;' . "\n"; + print HTML ' document.body.oncontextmenu = ContextShow;' . "\n"; + print HTML '}' . "\n"; + print HTML 'function ContextMouseDown(event) {' . "\n"; + print HTML ' if (_noContext || _mouseOverContext) return;' . "\n"; + print HTML ' if (event == null) event = window.event;' . "\n"; + print HTML ' var target = event.target != null ? event.target : event.srcElement;' . "\n"; + print HTML ' if (event.button == 2 && target.tagName.toLowerCase() == \'a\')' . "\n"; + print HTML ' _replaceContext = true;' . "\n"; + print HTML ' else if (!_mouseOverContext)' . "\n"; + print HTML ' _divContext.style.display = \'none\';' . "\n"; + print HTML '}' . "\n"; + print HTML 'function ContextShow(event) {' . "\n"; + print HTML ' if (_noContext || _mouseOverContext) return;' . "\n"; + print HTML ' if (event == null) event = window.event;' . "\n"; + print HTML ' var target = event.target != null ? event.target : event.srcElement;' . "\n"; + print HTML ' if (_replaceContext) {' . "\n"; + print HTML ' $(\'aRebuild\').href = \'http://'. $local_host_ip .':' . $html_port . '/rebuild=\' + target.id;' . "\n"; + print HTML ' $(\'aDelete\').href = \'http://'. $local_host_ip .':' . $html_port . '/delete=\' + target.id' . "\n"; + print HTML ' var scrollTop = document.body.scrollTop ? document.body.scrollTop : '; + print HTML 'document.documentElement.scrollTop;' . "\n"; + print HTML ' var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : '; + print HTML 'document.documentElement.scrollLeft;' . "\n"; + print HTML ' _divContext.style.display = \'none\';' . "\n"; + print HTML ' _divContext.style.left = event.clientX + scrollLeft + \'px\';' . "\n"; + print HTML ' _divContext.style.top = event.clientY + scrollTop + \'px\';' . "\n"; + print HTML ' _divContext.style.display = \'block\';' . "\n"; + print HTML ' _replaceContext = false;' . "\n"; + print HTML ' return false;' . "\n"; + print HTML ' }' . "\n"; + print HTML '}' . "\n"; + }; + print HTML 'function refreshInfoFrames() { ' . "\n"; print HTML ' var ModuleNameObj = top.innerFrame.frames[2].document.getElementById("ModuleErrors");' . "\n"; print HTML ' if (ModuleNameObj != null) {' . "\n"; @@ -2634,12 +3018,13 @@ sub generate_html_file { print HTML ' StatusInnerHtml += Status + "</em>";' . "\n"; print HTML ' return StatusInnerHtml;' . "\n"; print HTML '} ' . "\n"; - print HTML 'function ShowLog(LogFilePath) {' . "\n"; + print HTML 'function ShowLog(LogFilePath, ModuleJob) {' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("<h3 id=ModuleErrors name=\"" + null + "\">Log for " + ModuleJob + "</h3>");' . "\n"; + print HTML ' top.innerFrame.frames[2].document.write("<iframe id=LogFile name=Log src="'; if (defined $html_path) { - print HTML ' top.innerFrame.frames[2].document.location.replace("file://"+LogFilePath);' . "\n"; - } else { - print HTML ' top.innerFrame.frames[2].document.location.replace(LogFilePath);' . "\n"; + print HTML 'file://'; } + print HTML '+ LogFilePath + " width=100%></iframe>");' . "\n"; print HTML ' top.innerFrame.frames[2].document.close();' . "\n"; print HTML '};' . "\n"; print HTML 'function FillFrame_1(Module, Message1, Message2) {' . "\n"; @@ -2668,7 +3053,7 @@ sub generate_html_file { print HTML ' if (dir_info_array[4] == "@") {' . "\n"; print HTML ' top.innerFrame.frames[1].document.write(" <td style=white-space:nowrap>" + dir_info_array[1] + "</td>");' . "\n"; print HTML ' } else {' . "\n"; - print HTML ' top.innerFrame.frames[1].document.write(" <td><a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a></td>");' . "\n"; + print HTML ' top.innerFrame.frames[1].document.write(" <td><a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\', \'" + dir_info_array[1] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a></td>");' . "\n"; print HTML ' };' . "\n"; print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[2] + "</td>");' . "\n"; print HTML ' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[3] + "</td>");' . "\n"; @@ -2686,7 +3071,7 @@ sub generate_html_file { print HTML ' var DirectoryInfos = ModuleRows[i + 1].cells;' . "\n"; print HTML ' DirectoryInfos[0].innerHTML = getStatusInnerHTML(dir_info_array[0]) + " ";' . "\n"; print HTML ' if (dir_info_array[4] != "@") {' . "\n"; - print HTML ' DirectoryInfos[1].innerHTML = "<a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a>";' . "\n"; + print HTML ' DirectoryInfos[1].innerHTML = "<a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\', \'" + dir_info_array[1] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a>";' . "\n"; print HTML ' };' . "\n"; print HTML ' DirectoryInfos[2].innerHTML = dir_info_array[2];' . "\n"; print HTML ' DirectoryInfos[3].innerHTML = dir_info_array[3];' . "\n"; @@ -2789,7 +3174,7 @@ sub generate_html_file { print HTML ' document.write(\' </frameset>\');' . "\n"; print HTML ' document.write(\' <frame src="\');' . "\n"; print HTML ' document.write(urlquery[0]);' . "\n"; - print HTML ' document.write(\'?initFrame2"/>\');' . "\n"; + print HTML ' document.write(\'?initFrame2" name="infoframe"/>\');' . "\n"; print HTML ' document.write(\' </frameset>\');' . "\n"; print HTML ' document.write("</head></html>");' . "\n"; print HTML ' } else {' . "\n"; @@ -2877,7 +3262,7 @@ sub get_html_info { $errors_info_line .= '\''; # if (defined $full_info) { my $time_line = get_time_line($$module_info_hash{BUILD_TIME}); - my ($successes_percent, $errors_percent) = get_progress_percentage($dirs_number, $successful_number, $errorful_number); + my ($successes_percent, $errors_percent) = get_progress_percentage($dirs_number - 1, $successful_number - 1, $errorful_number); return($errors_info_line, $dirs_info_line, $errorful_number, $successes_percent, $errors_percent, $time_line); # } else { # return($errors_info_line, $dirs_info_line, $errorful_number); @@ -2929,7 +3314,11 @@ sub html_store_job_info { $build_dir =~ s/\\/\//g; $modules_with_errors{$module}++; } else { - $jobs_hash{$build_dir}->{STATUS} = 'success'; + if ($build_dir =~ /(\s)announce/o) { + $jobs_hash{$build_dir}->{STATUS} = '-'; + } else { + $jobs_hash{$build_dir}->{STATUS} = 'success'; + }; $dmake_array = $$module_info_hash{SUCCESSFUL}; }; push (@$dmake_array, $build_dir); @@ -2938,29 +3327,41 @@ sub html_store_job_info { sub start_server_on_port { my $port = shift; + my $socket_obj = shift; + $client_timeout = 1 if (!$parent_process); if ($ENV{GUI} eq 'WNT') { - $socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), + $$socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), LocalPort => $port, Proto => 'tcp', Listen => 100); # 100 clients can be on queue, I think it is enough } else { - $socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), + $$socket_obj = new IO::Socket::INET (#LocalAddr => hostname(), LocalPort => $port, Proto => 'tcp', ReuseAddr => 1, Listen => 100); # 100 clients can be on queue, I think it is enough }; - return('Cannot create socket object') if (!defined $socket_obj); - my $timeout = $socket_obj->timeout($client_timeout); - $socket_obj->autoflush(1); - print "SERVER started on port $port\n"; + return('Cannot create socket object') if (!defined $$socket_obj); + my $timeout = $$socket_obj->timeout($client_timeout); + $$socket_obj->autoflush(1); + if ($parent_process && $debug) { + print "SERVER started on port $port\n"; + } else { + print "html_port:$html_port html_socket_obj: $html_socket_obj\n"; + }; return 0; }; +sub accept_html_connection { + my $new_socket_obj = undef; + $new_socket_obj = $html_socket_obj->accept(); + return $new_socket_obj; +}; + sub accept_connection { my $new_socket_obj = undef; do { - $new_socket_obj = $socket_obj->accept(); + $new_socket_obj = $server_socket_obj->accept(); if (!$new_socket_obj) { print "Timeout on incoming connection\n"; check_client_jobs(); @@ -2985,9 +3386,7 @@ sub check_client_jobs { }; }; -sub run_server { - my @build_queue = (); # array, containing queue of projects - # to build +sub get_server_ports { # use port 7890 as default my $default_port = 7890; if ($ports_string) { @@ -2995,10 +3394,15 @@ sub run_server { } else { @server_ports = ($default_port .. $default_port + 4); }; +}; + +sub run_server { + my @build_queue = (); # array, containing queue of projects + # to build my $error = 0; if (scalar @server_ports) { foreach (@server_ports) { - $error = start_server_on_port($_); + $error = start_server_on_port($_, \$server_socket_obj); if ($error) { print STDERR "port $_: $error\n"; } else { @@ -3009,8 +3413,10 @@ sub run_server { last; }; }; + print_error('Unable to start server on port(s): ' . "@server_ports\n") if ($error); + } else { + print_error('No ports for server to start'); }; - print_error('It is impossible to start server on port(s): ' . "@server_ports\n") if ($error); my $client_addr; my $job_string_base = get_job_string_base(); @@ -3118,7 +3524,7 @@ sub get_job_string { } else { $dependencies_hash = \%LocalDepsHash; do { - $job_dir = PickPrjToBuild(\%LocalDepsHash); + $job_dir = pick_prj_to_build(\%LocalDepsHash); if (!$job_dir && !children_number()) { cancel_build() if (scalar keys %broken_build); mp_success_exit(); @@ -3160,20 +3566,18 @@ sub pick_jobdir { foreach (@$build_queue) { $Prj = $$build_queue[$i]; my $prj_deps_hash = $projects_deps_hash{$Prj}; - if (defined $broken_modules_hashes{$prj_deps_hash} && !$ignore) { + if (defined $modules_with_errors{$prj_deps_hash} && !$ignore) { push (@broken_modules_names, $Prj); splice (@$build_queue, $i, 1); next; }; - $only_dependent = 0; - $no_projects = 0; $running_children{$prj_deps_hash} = 0 if (!defined $running_children{$prj_deps_hash}); - $child_nick = PickPrjToBuild($prj_deps_hash); + $child_nick = pick_prj_to_build($prj_deps_hash); if ($child_nick) { return ($child_nick, $prj_deps_hash); } - if ($no_projects && !$running_children{$prj_deps_hash}) { - if (!defined $broken_modules_hashes{$prj_deps_hash} || $ignore) + if ((!scalar keys %$prj_deps_hash) && !$running_children{$prj_deps_hash}) { + if (!defined $modules_with_errors{$prj_deps_hash} || $ignore) { RemoveFromDependencies($Prj, \%global_deps_hash); $build_is_finished{$Prj}++; @@ -3188,10 +3592,10 @@ sub pick_jobdir { sub fill_modules_queue { my $build_queue = shift; my $Prj; - while ($Prj = PickPrjToBuild(\%global_deps_hash)) { + while ($Prj = pick_prj_to_build(\%global_deps_hash)) { push @$build_queue, $Prj; $projects_deps_hash{$Prj} = {}; - get_deps_hash($Prj, $projects_deps_hash{$Prj}); + get_module_dep_hash($Prj, $projects_deps_hash{$Prj}); my $info_hash = $html_info{$Prj}; $$info_hash{DIRS} = check_deps_hash($projects_deps_hash{$Prj}, $Prj); $module_by_hash{$projects_deps_hash{$Prj}} = $Prj; diff --git a/solenv/bin/cws.pl b/solenv/bin/cws.pl index ce6eaa015a91..1268f78ec186 100644 --- a/solenv/bin/cws.pl +++ b/solenv/bin/cws.pl @@ -39,6 +39,7 @@ use Getopt::Long; use File::Basename; use File::Path; use Cwd; +use Benchmark; #### module lookup my @lib_dirs; @@ -58,6 +59,10 @@ use Cws; #### globals #### +# TODO: replace dummy vales with actual SVN->hg migration milestones +my $dev300_migration_milestone = 'm999'; +my $ooo320_migration_milestone = 'm999'; + # valid command with possible abbreviations my @valid_commands = ( 'help', 'h', '?', @@ -360,7 +365,13 @@ sub get_cws_by_name # Update masterws part of Cws object. my $masterws = $cws->get_mws(); - $cws->master($masterws); + if ( $cws->master() ne $masterws ) { + # can this still happen? + if ( $debug ) { + print STDERR "CWS-DEBUG: get_cws_by_name(): fixup of masterws in cws object detected\n"; + } + $cws->master($masterws); + } return ($cws); } @@ -426,6 +437,191 @@ sub register_child_workspace return 0; } +sub print_time_elapsed +{ + my $t_start = shift; + my $t_stop = shift; + + my $time_diff = timediff($t_stop, $t_start); + print_message("... finished in " . timestr($time_diff)); +} + +sub hgrc_append_default_push_path +{ + my $target = shift; + my $cws_source = shift; + + $cws_source =~ s/http:\/\//ssh:\/\/hg@/; + if ( $debug ) { + print STDERR "CWS-DEBUG: default-push path: '$cws_source'\n"; + } + if ( !open(HGRC, ">>$target/.hg/hgrc") ) { + print_error("Can't append default-push path to hgrc file of repository '$target'.\n", 88); + } + print HGRC "default-push = " . "$cws_source\n"; + close(HGRC); +} + +sub hg_clone_repository +{ + my $rep_type = shift; + my $cws = shift; + my $target = shift; + my $clone_milestone_only = shift; + + my ($hg_local_source, $hg_lan_source, $hg_remote_source); + my $config = CwsConfig->new(); + if ( $rep_type eq 'ooo') { + $hg_local_source = $config->get_ooo_hg_local_source(); + $hg_lan_source = $config->get_ooo_hg_lan_source(); + $hg_remote_source = $config->get_ooo_hg_remote_source(); + } + else { + $hg_local_source = $config->get_so_hg_local_source(); + $hg_lan_source = $config->get_so_hg_lan_source(); + $hg_remote_source = $config->get_so_hg_remote_source(); + } + + my $masterws = $cws->master(); + my $master_local_source = "$hg_local_source/" . $masterws; + my $master_lan_source = "$hg_lan_source/" . $masterws; + + my $milestone_tag; + if ( $clone_milestone_only ) { + $milestone_tag = uc($masterws) . '_' . $clone_milestone_only; + } + else { + my @tags = $cws->get_tags(); + $milestone_tag = $tags[3]; + } + + if ( $debug ) { + print STDERR "CWS-DEBUG: master_local_source: '$master_local_source'\n"; + print STDERR "CWS-DEBUG: master_lan_source: '$master_lan_source'\n"; + if ( !-d $master_local_source ) { + print STDERR "CWS-DEBUG: not a directory '$master_local_source'\n"; + } + } + + # clone from local source if possible, otherwise from LAN source + if ( -d $master_local_source && can_use_hardlinks($master_local_source, dirname($target)) ) { + hg_local_clone_repository($master_local_source, $target, $milestone_tag); + } + else { + hg_lan_clone_repository($master_lan_source, $target, $milestone_tag); + } + + # now pull from the remote cws outgoing repository if it already contains something + if ( !$clone_milestone_only ) { + my $cws_remote_source = "$hg_remote_source/cws/" . $cws->child(); + + # The outgoing repository might not yet be available. Which is not + # an error. Since pulling from the cws outgoing URL results in an ugly + # and hardly understandable error message, we check for the availaility + # first. TODO: incorporate configured proxy instead of env_proxy. Use + # a dedicated request and content-type to find out if the repo is there + # instead of parsing the content of the page + require LWP::Simple; + my $content = LWP::Simple::get($cws_remote_source); + my $pattern = "<title>cws/". $cws->child(); + if ( $content =~ /$pattern/ ) { + hg_remote_pull_repository($cws_remote_source, $target); + hgrc_append_default_push_path($target, $cws_remote_source); + } + else { + print_message("The 'outgoing' repository '$cws_remote_source' is not accessible/available"); + } + } + + # update the result + hg_update_repository($target); + +} + +sub hg_local_clone_repository +{ + my $local_source = shift; + my $dest = shift; + my $milestone_tag = shift; + + # fastest way to clone a repository up to a certain milestone + # 1) clone w/o -r options (hard links!) + # 2) find (local) revision which corresponds to milestone + # 3) strip revision+1 + + my $t1 = Benchmark->new(); + print_message("... clone LOCAL repository '$local_source' to '$dest'"); + hg_clone($local_source, $dest, '-U'); + my $id_option = "-n -r $milestone_tag"; + my $revision = hg_ident($dest, $milestone_tag); + if ( defined($revision) ) { + my $strip_revision = $revision+1; + hg_strip($dest, $revision); + } + my $t2 = Benchmark->new(); + print_time_elapsed($t1, $t2); +} + +sub hg_lan_clone_repository +{ + my $lan_source = shift; + my $dest = shift; + my $milestone_tag = shift; + + my $t1 = Benchmark->new(); + print_message("... clone LAN repository '$lan_source' to '$dest'"); + hg_clone($lan_source, $dest, "-U -r $milestone_tag"); + my $t2 = Benchmark->new(); + print_time_elapsed($t1, $t2); +} + +sub hg_remote_pull_repository +{ + my $remote_source = shift; + my $dest = shift; + + my $t1 = Benchmark->new(); + print_message("... pull from REMOTE repository '$remote_source' to '$dest'"); + hg_pull($dest, $remote_source); + my $t2 = Benchmark->new(); + print_time_elapsed($t1, $t2); +} + +sub hg_update_repository +{ + my $dest = shift; + + my $t1 = Benchmark->new(); + print_message("... update repository '$dest'"); + hg_update($dest); + my $t2 = Benchmark->new(); + print_time_elapsed($t1, $t2); +} + +# Check if clone source and destination are on the same filesystem, +# in that case hg clone can employ hard links. +sub can_use_hardlinks +{ + my $source = shift; + my $dest = shift; + + if ( $^O eq 'cygwin' ) { + # no hard links on windows + return 0; + } + # st_dev is the first field return by stat() + my @stat_source = stat($source); + my @stat_dest = stat($dest); + + if ( $debug ) { + print STDERR "can_use_hardlinks(): source device: '$stat_source[0]', destination device: '$stat_dest[0]'\n"; + } + if ( $stat_source[0] == $stat_dest[0] ) { + return 1; + } + return 0; +} + sub query_cws { my $query_mode = shift; @@ -530,7 +726,6 @@ sub query_scm print_message("Child workspace uses '$scm'."); } } - return; } @@ -1217,6 +1412,49 @@ sub diff_print_files } } +# TODO: special provisions for SVN->HG migrations, remove this +# some time after migration +sub get_scm_for_milestone +{ + my $masterws = shift; + my $milestone = shift; + + my $milestone_sequence_number = extract_milestone_sequence_number($milestone); + my $dev300_migration_sequence_number = extract_milestone_sequence_number($dev300_migration_milestone); + my $ooo320_migration_sequence_number = extract_milestone_sequence_number($ooo320_migration_milestone); + + my $scm = 'SVN'; + + if ( $masterws eq 'DEV300' ) { + if ( $milestone_sequence_number >= $dev300_migration_sequence_number ) { + $scm = 'HG'; + } + } + elsif ( $masterws eq 'OOO320' ) { + if ( $milestone_sequence_number >= $ooo320_migration_sequence_number ) { + $scm = 'HG'; + } + } + else { + $scm = 'SVN' + } + return $scm; +} + +sub extract_milestone_sequence_number +{ + my $milestone = shift; + + my $milestone_sequence_number; + if ( $milestone =~ /m(\d+)/ ) { + $milestone_sequence_number = $1; + } + else { + print_error("can't extract milestone sequence number from milestone '$milestone'", 99); + } + return $milestone_sequence_number; +} + # Executes the help command. sub do_help { @@ -1772,6 +2010,7 @@ sub do_fetch my $args_ref = shift; my $options_ref = shift; + my $time_fetch_start = Benchmark->new(); if ( exists $options_ref->{'help'} || @{$args_ref} != 1) { do_help(['fetch']); } @@ -1794,7 +2033,7 @@ sub do_fetch } if ( defined($platforms) && $switch ) { - print_error("Option '-p' is not yet usuable with Option '-s'. Will be fixed RSN.", 0); + print_error("Option '-p' is not usuable with Option '-s'.", 0); do_help(['fetch']); } @@ -1810,6 +2049,7 @@ sub do_fetch } $cws->master($masterws); my $milestone; + my $scm; if( defined($milestone_opt) ) { if ( $milestone_opt eq 'latest' ) { $cws->master($masterws); @@ -1823,16 +2063,26 @@ sub do_fetch else { ($masterws, $milestone) = verify_milestone($cws, $milestone_opt); } + $scm = get_scm_for_milestone($masterws, $milestone); } elsif ( defined($child) ) { $cws = get_cws_by_name($child); $masterws = $cws->master(); # CWS can have another master than specified in ENV $milestone = $cws->milestone(); + $scm = $cws->get_scm(); } else { do_help(['fetch']); } + if ( $switch && $scm eq 'HG' ) { + print_error("Option '-s' is not supported on a hg based CWS.", 0); + do_help(['fetch']); + } + + if ( $debug ) { + print STDERR "CWS-DEBUG: SCM: $scm\n"; + } my $config = CwsConfig->new(); my $ooo_svn_server = $config->get_ooo_svn_server(); my $so_svn_server = $config->get_so_svn_server(); @@ -1886,11 +2136,12 @@ sub do_fetch } my $cwsname = $cws->child(); - my $url_suffix = $milestone_opt ? ("/tags/$masterws" . "_$milestone") : ('/cws/' . $cwsname); my $linkdir = $milestone_opt ? "src.$milestone" : "src." . $cws->milestone; my $workspace = $args_ref->[0]; + if ( !$onlysolver ) { + my $url_suffix = $milestone_opt ? ("/tags/$masterws" . "_$milestone") : ('/cws/' . $cwsname); if ( $switch ) { # check if to be switched working copy exist or bail out if ( ! -d $workspace ) { @@ -1942,8 +2193,11 @@ sub do_fetch print_error("File or directory '$workspace' already exists.", 8); } - # Check if working directory already exists + if ( !(($scm eq 'SVN') || ($scm eq 'HG')) ) { + print_error("Unsupported SCM '$scm'.", 8); + } + my $clone_milestone_only = $milestone_opt ? $milestone : 0; if ( defined($so_svn_server) ) { if ( !mkdir($workspace) ) { print_error("Can't create directory '$workspace': $!.", 8); @@ -1952,11 +2206,17 @@ sub do_fetch if ( !mkdir($work_master) ) { print_error("Can't create directory '$work_master': $!.", 8); } - print_message("... checkout '$ooo_url' to '$work_master/ooo'"); - svn_checkout($ooo_url, "$work_master/ooo", $quiet); - my $so_url = $so_svn_server . $url_suffix; - print_message("... checkout '$so_url' to '$work_master/sun'"); - svn_checkout($so_url, "$work_master/sun", $quiet); + if ( $scm eq 'SVN' ) { + print_message("... checkout '$ooo_url' to '$work_master/ooo'"); + svn_checkout($ooo_url, "$work_master/ooo", $quiet); + my $so_url = $so_svn_server . $url_suffix; + print_message("... checkout '$so_url' to '$work_master/sun'"); + svn_checkout($so_url, "$work_master/sun", $quiet); + } + else{ + hg_clone_repository('ooo', $cws, "$work_master/ooo", $clone_milestone_only); + hg_clone_repository('so', $cws, "$work_master/sun", $clone_milestone_only); + } my $linkdir = "$work_master/src.$milestone"; if ( !mkdir($linkdir) ) { print_error("Can't create directory '$linkdir': $!.", 8); @@ -1964,8 +2224,13 @@ sub do_fetch relink_workspace($linkdir); } else { - print_message("... checkout '$ooo_url' to '$workspace'"); - svn_checkout($ooo_url, $workspace, $quiet); + if ( $scm eq 'SVN' ) { + print_message("... checkout '$ooo_url' to '$workspace'"); + svn_checkout($ooo_url, $workspace, $quiet); + } + else { + hg_clone_repository('ooo', $cws, $workspace, $clone_milestone_only); + } } } } @@ -1983,10 +2248,16 @@ sub do_fetch } } foreach(@platforms) { + my $time_solver_start = Benchmark->new(); print_message("... copying platform solver '$_'."); update_solver($_, $prebuild_dir, $solver, $milestone); + my $time_solver_stop = Benchmark->new(); + print_time_elapsed($time_solver_start, $time_solver_stop); } } + my $time_fetch_stop = Benchmark->new(); + my $time_fetch = timediff($time_fetch_stop, $time_fetch_start); + print_message("cws fetch: total time required " . timestr($time_fetch)); } sub do_query @@ -2608,4 +2879,116 @@ sub execute_svnversion_command return $result; } + +### HG glue ### + +sub hg_clone +{ + my $source = shift; + my $dest = shift; + my $options = shift; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... hg clone: '$source -> $dest', options: '$options'\n"; + } + + my @result = execute_hg_command(1, 'clone', $options, $source, $dest); + return @result; +} + +sub hg_ident +{ + my $repository = shift; + my $rev_id = shift; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... hg ident: 'repository', revision: '$rev_id'\n"; + } + + my @result = execute_hg_command(0, 'ident', "--cwd $repository", "-n -r $rev_id"); + my $line = $result[0]; + if ($line =~ /abort: unknown revision/) { + return undef; + } + else { + chomp($line); + return $line; + } +} + +sub hg_strip +{ + my $repository = shift; + my $rev_id = shift; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... hg strip: 'repository', revision: '$rev_id'\n"; + } + + my @result = execute_hg_command(1, 'strip', "--cwd $repository", '-n', $rev_id); + my $line = $result[0]; + if ($line =~ /abort: unknown revision/) { + return undef; + } + else { + chomp($line); + return $line; + } +} + +sub hg_pull +{ + my $repository = shift; + my $remote = shift; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... hg pull: 'repository', remote: '$remote'\n"; + } + + my @result = execute_hg_command(0, 'pull', "--cwd $repository", $remote); + my $line = $result[0]; + if ($line =~ /abort: /) { + return undef; + } +} + +sub hg_update +{ + my $repository = shift; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... hg update: 'repository'\n"; + } + + my @result = execute_hg_command(1, 'update', "--cwd $repository"); + return @result; +} + +sub execute_hg_command +{ + my $terminate_on_rc = shift; + my $command = shift; + my $options = shift; + my @args = @_; + + my $args_str = join(" ", @args); + + # we can only parse english strings, hopefully a C locale is available everywhere + $ENV{LC_ALL}='C'; + $command = "hg $command $options $args_str"; + + if ( $debug ) { + print STDERR "CWS-DEBUG: ... execute command line: '$command'\n"; + } + + my $result = `$command`; + my $rc = $? >> 8; + if ($rc > 0 && $terminate_on_rc) { + print_error("The mercurial command line tool 'hg' failed with exit status '$rc'", 99); + } + + return $result; +} + + # vim: set ts=4 shiftwidth=4 expandtab syntax=perl: diff --git a/solenv/bin/modules/Cws.pm b/solenv/bin/modules/Cws.pm index d5516bd79e66..2ec5d13ff88c 100755 --- a/solenv/bin/modules/Cws.pm +++ b/solenv/bin/modules/Cws.pm @@ -1219,7 +1219,7 @@ sub register_child_with_eis }; if ( $@ ) { - carp("ERROR: create_child_wortkspace(): EIS database transaction failed. Reason:\n$@\n"); + carp("ERROR: create_child_workspace(): EIS database transaction failed. Reason:\n$@\n"); return undef; } # set EIS_ID directly, since $self->eis_id() is not @@ -1828,6 +1828,7 @@ sub set_scm_in_eis my $self = shift; my $scm_name = shift; + $scm_name = Eis::to_string($scm_name); # check if child workspace is valid my $id = $self->eis_id(); if ( !$id ) { diff --git a/solenv/bin/modules/CwsConfig.pm b/solenv/bin/modules/CwsConfig.pm index a346ba7d4d50..3574bc89e7a8 100644 --- a/solenv/bin/modules/CwsConfig.pm +++ b/solenv/bin/modules/CwsConfig.pm @@ -345,6 +345,98 @@ sub get_so_svn_server return $self->{SO_SVN_SERVER} ? $self->{SO_SVN_SERVER} : undef; } +#### HG methods #### + +sub get_ooo_hg_local_source +{ + my $self = shift; + + if ( !defined($self->{HG_LOCAL_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'HG_LOCAL_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{HG_LOCAL_SOURCE} = $source; + } + return $self->{HG_LOCAL_SOURCE} ? $self->{HG_LOCAL_SOURCE} : undef; +} + +sub get_ooo_hg_lan_source +{ + my $self = shift; + + if ( !defined($self->{HG_LAN_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'HG_LAN_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{HG_LAN_SOURCE} = $source; + } + return $self->{HG_LAN_SOURCE} ? $self->{HG_LAN_SOURCE} : undef; +} + +sub get_ooo_hg_remote_source +{ + my $self = shift; + + if ( !defined($self->{HG_REMOTE_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'HG_REMOTE_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{HG_REMOTE_SOURCE} = $source; + } + return $self->{HG_REMOTE_SOURCE} ? $self->{HG_REMOTE_SOURCE} : undef; +} + +sub get_so_hg_local_source +{ + my $self = shift; + + if ( !defined($self->{SO_HG_LOCAL_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'SO_HG_LOCAL_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{SO_HG_LOCAL_SOURCE} = $source; + } + return $self->{SO_HG_LOCAL_SOURCE} ? $self->{SO_HG_LOCAL_SOURCE} : undef; +} + +sub get_so_hg_lan_source +{ + my $self = shift; + + if ( !defined($self->{SO_HG_LAN_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'SO_HG_LAN_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{SO_HG_LAN_SOURCE} = $source; + } + return $self->{SO_HG_LAN_SOURCE} ? $self->{SO_HG_LAN_SOURCE} : undef; +} + +sub get_so_hg_remote_source +{ + my $self = shift; + + if ( !defined($self->{SO_HG_REMOTE_SOURCE}) ) { + my $config_file = $self->get_config_file(); + my $source = $config_file->{CWS_CONFIG}->{'SO_HG_REMOTE_SOURCE'}; + if ( !defined($source) ) { + $source = ""; + } + $self->{SO_HG_REMOTE_SOURCE} = $source; + } + return $self->{SO_HG_REMOTE_SOURCE} ? $self->{SO_HG_REMOTE_SOURCE} : undef; +} + #### Prebuild binaries configuration #### sub get_prebuild_binaries_location diff --git a/solenv/bin/rpm-wrapper b/solenv/bin/rpm-wrapper index 1b523bb9b130..1c94bc0a9f10 100755 --- a/solenv/bin/rpm-wrapper +++ b/solenv/bin/rpm-wrapper @@ -40,6 +40,12 @@ then LD_LIBRARY_PATH=${LD_LIBRARY_PATH+${LD_LIBRARY_PATH}:}${LIBRARY_PATH?} \ ${BUILD_TOOLS?}/rpmbuild "$@" else +if [ "$OUTPATH" = "unxlngx6" ] +then +LD_LIBRARY_PATH=${LD_LIBRARY_PATH+${LD_LIBRARY_PATH}:}${LIBRARY_PATH?} \ + ${BUILD_TOOLS?}/rpmbuild "$@" +else LD_LIBRARY_PATH=${LD_LIBRARY_PATH+${LD_LIBRARY_PATH}:}${COMPATH?}/lib \ ${BUILD_TOOLS?}/rpm "$@" fi +fi |