: eval 'exec perl -wS $0 ${1+"$@"}' if 0; #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # Copyright 2008 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite # # $RCSfile: cwsadd.pl,v $ # # $Revision: 1.10 $ # # This file is part of OpenOffice.org. # # OpenOffice.org is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # only, as published by the Free Software Foundation. # # OpenOffice.org is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License version 3 for more details # (a copy is included in the LICENSE file that accompanied this code). # # You should have received a copy of the GNU Lesser General Public License # version 3 along with OpenOffice.org. If not, see # # for a copy of the LGPLv3 License. # #************************************************************************* # # cwsadd.pl - add modules to child workspaces # use strict; use Getopt::Long; use Cwd; use IO::Handle; use File::Copy; #### module lookup my @lib_dirs; BEGIN { if ( !defined($ENV{SOLARENV}) ) { die "No environment found (environment variable SOLARENV is undefined)"; } push(@lib_dirs, "$ENV{SOLARENV}/bin/modules"); push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS}); } use lib (@lib_dirs); use Cws; use CwsConfig; eval { require CopyPrj; import CopyPrj; }; use CvsModule; #### script id ##### ( my $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; my $script_rev; my $id_str = ' $Revision: 1.10 $ '; $id_str =~ /Revision:\s+(\S+)\s+\$/ ? ($script_rev = $1) : ($script_rev = "-"); print "$script_name -- version: $script_rev\n"; #### global ##### my $force_checkout = ''; my $allow_modified = 0; my $is_debug = 0; my $opt_dir = ''; # dir option my $vcsid = "unknown"; my $add_output_tree = 1; my $keep_output_trees = 0; my $force_output_tree_copy = 0; my $sointernal = undef; my @found_platforms = (); my @args_bak = @ARGV; # store the @ARGS here for logging # module names to be rejected my @invalid_names = qw(common common.pro cvs cws wntmsci unxsols unxsoli unxlngi unxlngp macosxp); #### main ##### my @modules = parse_options(); my ($dir, $cws) = get_and_verify_cws(); my @modules_to_add = check_modules($cws, @modules); my $workspace_db; if ( @modules_to_add ) { if ($sointernal) { require EnvHelper; import EnvHelper; $workspace_db = EnvHelper::get_workspace_db(); @modules_to_add = copy_modules($cws, $dir, $workspace_db, @modules_to_add); } else { @modules_to_add = update_modules($cws, $dir, @modules_to_add); }; if ( @modules_to_add ) { my @registered_modules = (); my $success = 0; my $module; foreach (@modules_to_add) { $module = $_; $success = branch_module($cws, $dir, $module); last unless $success; $success = register_module($cws, $workspace_db, $module); last unless $success; push(@registered_modules, $module); } if ( @registered_modules ) { my $modules_str = join(", ", @registered_modules); my $child = $cws->child(); print "\n"; print_message("Summary:"); print_message("Sucessfully added and registered module(s) '$modules_str'."); } if ( !$success ) { print_error("Adding and/or registering module '$module' failed!", 5); } } } exit(0); #### subroutines #### # # Subroutine updates module # sub update_modules { my ($cws, $stand_dir, @modules_to_update) = @_; my (@updated_modules, @rejected_modules); my $master_tag = $cws->get_master_tag(); foreach my $module (@modules_to_add) { my $cvs_module = CvsModule->new(); $cvs_module->module($module); print "\tUpdating '$module' ...\n"; my $result = $cvs_module->update($stand_dir, $master_tag); my ($updated, $merged, $conflicts) = $cvs_module->handle_update_information($result); if ( ( $merged && ! $allow_modified ) || $conflicts ) { push(@rejected_modules, $module); next; }; push(@updated_modules, $module); }; if (@rejected_modules) { print_warning("Found conflicts and/or locally modified files in the following modules:"); print STDERR "$_\n" foreach (@rejected_modules); print_warning("These modules will not be added to CWS. Clean up and try adding them again."); }; return @updated_modules; }; sub get_and_verify_cws { # get current child workspace from environment my $childws = $ENV{CWS_WORK_STAMP}; my $masterws = $ENV{WORK_STAMP}; if ( !defined($childws) || !defined($masterws) ) { print_error("Can't determine child workspace environment.\n" . "Please initialize environment with setsolar ...", 1); } # get destination directory for modules to add my $dir = $ENV{SRC_ROOT}; if ( !defined($dir) ) { print_error("Need to get destination from SOURCE_ROOT - but it's not defined!",1); } my $cws = Cws->new(); $cws->child($childws); $cws->master($masterws); # check if we got a valid child workspace my $id = $cws->eis_id(); print "Master: $masterws, Child: $childws, $id\n" if $is_debug; if ( !$id ) { print_error("Child workspace $childws for master workspace $masterws not found in EIS database.", 2); } return ($dir, $cws); } sub parse_options { # parse options and do some sanity checks # returns freshly allocated Cws reference # linking and unlinking requires UNIX if ( $^O =~ "MSWin32" ) { print_error("Sorry! not for non-cygwin Windows environment",2); } my $help; my $success = GetOptions( '-h' => \$help, '-a' => \$force_checkout, '-f' => \$allow_modified, '-o' => \$force_output_tree_copy, '-k' => \$keep_output_trees ); if ( $force_checkout && $force_output_tree_copy ) { print_error ("Can't copy output trees with checkout forced!", 2); } if ( $keep_output_trees && $force_output_tree_copy ) { print_error ("Can't copy output trees but keep existing...", 2); } if ( $help || !$success || $#ARGV < 0 ) { usage(); exit(1); } return @ARGV; } sub check_modules { # check if modules are registered with child workspace # returns list of modules which can be added my $cws = shift; my @modules = @_; my @registered_modules = $cws->modules(); # create hash for easier searching my %registered_modules_hash = (); for (@registered_modules) { $registered_modules_hash{$_}++; } my %invalid_names_hash = (); for (@invalid_names) { $invalid_names_hash{$_}++; } my $config = CwsConfig->get_config(); $sointernal = $config->sointernal(); my $cvs_module = CvsModule->new(); $cvs_module->cvs_method($config->get_cvs_server_method()); $cvs_module->vcsid($config->get_cvs_server_id()); $cvs_module->cvs_server($config->get_cvs_server()); $cvs_module->cvs_repository($config->get_cvs_server_repository()); my @new_modules = (); my %cvs_aliases = $cvs_module->get_aliases_hash(); foreach (@modules) { if ( $_ =~ /[\s\t\|\$\(\)\[\]\{\\}]/ || exists $invalid_names_hash{lc($_)} ) { print_error("'$_' is an invalid module name.", 3); } if ( exists $registered_modules_hash{$_} ) { print_warning("Module '$_' already registered, skipping."); next; }; if (!($sointernal) && !defined $cvs_aliases{$_}) { print_error("There is no such module alias '$_'.", 3); }; push(@new_modules, $_); } return @new_modules; } sub copyprj_module_sourcetree { my $module_name = shift; my $src_dest = shift; print "copyprj $module_name\n"; # hash, that should contain all the # data needed by CopyPrj module my %ENVHASH = (); my %platforms_to_copy = (); $ENVHASH{'platforms_hash'} = \%platforms_to_copy; if ( $add_output_tree && !$force_checkout ) { $platforms_to_copy{$_}++ foreach (@found_platforms); }; my %projects_to_copy = (); $ENVHASH{'projects_hash'} = \%projects_to_copy; $ENVHASH{'no_otree'} = 1; # does this match with %platforms_to_copy??? $ENVHASH{'no_path'} = 1; $ENVHASH{'only_otree'} = 0; $ENVHASH{'only_update'} = 1; $ENVHASH{'last_minor'} = 0; $ENVHASH{'spec_src'} = 0; $ENVHASH{'dest'} = "$src_dest"; $ENVHASH{'prj_to_copy'} = ''; $ENVHASH{'i_server'} = ''; $ENVHASH{'current_dir'} = cwd(); $ENVHASH{'remote'} = ''; $ENVHASH{'force_checkout'} = 1 if ($force_checkout); $projects_to_copy{$module_name}++; CopyPrj::copy_projects(\%ENVHASH); }; sub copy_modules { # copy modules from master workspace into child workspace my $cws = shift; my $dir = shift; my $workspace_db = shift; my @modules = @_; my $masterws = $cws->master(); my $childws = $cws->child(); my $milestone = $cws->milestone(); # ause: Deine Spielwiese my $result; my @success_modules = (); my $workspace = $workspace_db->get_key($masterws); if ( !$workspace ) { print_error("Master workspace '$masterws' not found in workspace database.", 3); } my $wslocation = $workspace_db->get_value($masterws."/Drives/o:/UnixVolume"); if ( !defined($wslocation) ) { print_error("Location of master workspace '$masterws' not found in workspace database.", 3); } print "$wslocation\n" if $is_debug; my $source_root = $ENV{SOURCE_ROOT}; if ( !defined( $source_root )) { print_error("SOURCE_ROOT not defined! Please setup a valid environment for CWS \"$childws\"", 1); } my $cws_solver = "$source_root/$masterws"; my $start_dir = getcwd(); $result = chdir($dir); if ( !$result ) { print_error("Cannot change to $dir!", 1); } # assume that every valid platform on child "solver" has to be copied $result = opendir( SOLVER, "$cws_solver"); if ( !$result ){ print_error ("Root dir of child workspace not accessible: $!", 1) }; my @found_dirs = readdir( SOLVER ); closedir( SOLVER ); # hack to get the milestone :-((((( if ( ! defined($milestone)) { $milestone = $ENV{UPDMINOR}; } if ( $#found_dirs ) { foreach my $dir_candidate ( @found_dirs ) { if ( -d "$cws_solver/$dir_candidate/inc.".$milestone ) { push @found_platforms, $dir_candidate; } } } # preparing pseudo environment for copyprj $ENV{SRC_ROOT}="$wslocation/$masterws/src.$ENV{UPDMINOR}"; print "$ENV{SRC_ROOT}\n" if ( $is_debug ); print "working dir: ".getcwd()."\n" if ( $is_debug ); foreach my $one_module (@modules) { # do some snity checks for this module if ( -e "$one_module.lnk" && -e "$one_module" ) { print_error("Duplicate representation of module $one_module ($one_module.lnk $one_module)", 0); print_error("Please clean up!", 0); print_error("Will NOT add module $one_module to child workspace!", 0); # fail for this module next; } if ( -e "$one_module.backup.lnk" || -e "$one_module.backup" ) { print_error("Backup of module $one_module already exists.", 0); print_error("Please clean up!", 0); print_error("Will NOT add module $one_module to child workspace!", 0); # fail for this module next; } $result = 0; $result = rename($one_module, "$one_module.backup.lnk") if ( -l $one_module ); if ( ! -l $one_module && -e $one_module ) { $result ||= rename($one_module, "$one_module.backup"); # if it is no link, assume incompatible build # -> don't copy output tree unless required $add_output_tree = 0 if ( !$force_output_tree_copy ); } $result ||= rename("$one_module.lnk", "$one_module.backup.lnk") if ( -e "$one_module.lnk" ); $result = 0 if ( -e $one_module || -e "$one_module.lnk" ); if ( ! $result ) { print_error("Couldn't backup existing module $one_module before copying", 0); print_error("Will NOT add module $one_module to child workspace!", 0); # fail for this module next; } # now copy sources $result = copyprj_module_sourcetree( $one_module, "." ); if ( $result ) { if ( -d $one_module ) { $result = rename("$one_module", "$one_module.failed"); $result = system("rm -rf $one_module.failed"); } print_error("Couldn't copy module $one_module, restoring previous.", 0); if ( -e "$one_module.backup" ) { $result = rename("$one_module.backup", $one_module); } else { $result = rename("$one_module.backup.lnk", "$one_module.lnk"); } print_error("Restoring link for $one_module failed! Cleanup is in your hands now", 1) if ( ! $result ); # fail for this module next; } # remove backuped link unlink("$one_module.backup.lnk") if -l "$one_module.backup.lnk"; # or backuped directory... if ( -d "$one_module.backup" ) { my $keep_this_module = 0; if ( $^O =~ "MSWin32" || $^O =~ "cygwin" ) { print_error("Sorry! not for windows, nobody should ever get here!",2); } if ( $keep_output_trees ) { # copy output trees from backup to added module foreach my $i ( @found_platforms ) { if ( ! move "$one_module.backup/$i", "$one_module/$i" ) { print_warning("Could not keep \"$one_module/$i\" autommatically."); print_warning("Keeping backuped module \"$one_module.back\" to allow manual copying..."); $keep_this_module = 1; } } } if ( ! $keep_this_module ) { $result = system("rm -rf $one_module.backup"); print_warning("Couldn't remove backuped module \"$one_module.backup\".") if $result; } } # insert module in list of successfull copied modules push(@success_modules, $one_module); } chdir($start_dir); # return my @empty = (); # ause - disable all further steps return @success_modules; } sub branch_module { # tag modules with cws branch cws root tag my $cws = shift; my $dir = shift; my $module = shift; my ($cws_master_tag, $cws_branch_tag, $cws_root_tag) = $cws->get_tags(); # Sanity check print "operating on $dir/$_\n" if $is_debug; if ( -S "$dir/$module" || ! -d "$dir/$module" ) { print_error("Can't find physical copy of module '$module'", 4); } STDOUT->autoflush(1); print_message("Tagging module '$module'."); my $cvs_module = CvsModule->new(); $cvs_module->module($module); $cvs_module->verbose(1); print_message("Tag with branch tag '$cws_branch_tag'."); my ($branched_files, $branch_errors) = $cvs_module->tag($dir, $cws_branch_tag, '-b'); if ( $branched_files < 1 ) { print_error("Tagging module '$module' failed.", 0); return 0; } if ( $branch_errors > 0 ) { print_error(cleanup_tags_msg($module), 0); return 0; } print_message("Tagged $branched_files files in module '$module' with branch tag."); print_message("Tag with tag '$cws_root_tag'."); my ($tagged_files, $anchor_errors) = $cvs_module->tag($dir, $cws_root_tag); if ( $tagged_files < 1 || $anchor_errors > 0 || $branched_files != $tagged_files ) { print_error(cleanup_tags_msg($module), 0); return 0; } print_message("Tagged $tagged_files files in module '$module'."); print_message("Updating module '$module' to branch '$cws_branch_tag'."); my @dirs = $cvs_module->update($dir, $cws_branch_tag); if ( $#dirs < 0 ) { print_error("Updating module '$module' to branch '$cws_branch_tag' failed.\n", 0); return 0; } STDOUT->autoflush(0); return 1; } sub cleanup_tags_msg { my $module = shift; my ($cws_master_tag, $cws_branch_tag, $cws_root_tag) = $cws->get_tags(); my $msg = "Tagging module '$module' failed partly. Can't continue.\n"; $msg .= "Please remember to manually remove the tags '$cws_branch_tag' and '$cws_root_tag'\n"; $msg .= "from module '$module' before retrying the operation!"; return $msg; } # Register module with EIS. sub register_module { my $cws = shift; my $workspace_db = shift; my $module = shift; my $public = 1; # find out if module has public flag my $master = $cws->master(); if ($sointernal) { my $key = "$master/Drives/o:/Projects/$module/SCS"; my $scs = $workspace_db->get_value($key); if ( !defined($scs) ) { print_error("Can't find module '$module' in workspace db", 0); return 0; } # FIXME - this really shouldn't be hard coded if ( $scs !~ /tunnel/ ) { $public = 0; } } my $success = $cws->add_module($module, $public); if ( !$success ) { print_error("Can't register module '$module' with EIS!", 0); return 0; } print_message("Succesfully registered module '$module'."); return 1; } sub print_message { my $message = shift; print "$script_name: "; print "$message\n"; return; } sub print_warning { my $message = shift; print STDERR "$script_name: "; print STDERR "WARNING: $message\n"; return; } sub print_error { my $message = shift; my $error_code = shift; print STDERR "$script_name: "; print STDERR "ERROR: $message\n"; if ( $error_code ) { print STDERR "\nFAILURE: $script_name aborted.\n"; exit($error_code); } return; } sub usage { print STDERR "Usage: cwsadd [-h] [-a] [-f ] [-o|-k] ... \n"; print STDERR "Add one or more modules to child workspace.\n"; print STDERR "Options:\n"; print STDERR " -a use cvs checkout instead of copying\n"; print STDERR " -f incorporate modified files into cws\n"; print STDERR " -o force copying output trees (in copy mode only)\n"; print STDERR " -k keep existing output trees\n"; print STDERR " -h print this help\n"; }