Commits

Anonymous committed 165af18 Merge

CWS-TOOLING: integrate CWS vgbugs10_OOO330

Comments (0)

Files changed (4)

 ^[^/]+/unxsols\d+(\.pro)?$
 ^[^/]+/wntgcci(\.pro)?$
 ^[^/]+/wntmsci\d+(\.pro)?$
-^[^/]+\.pro\.build\.html$
 ^solver$
 
 # Emacs backups (XXX~, #XXX#, .#XXX):

solenv/bin/build.pl

 
     use lib ("$ENV{SOLARENV}/bin/modules");
     use SourceConfig;
+    use RepositoryHelper;
     
     my $in_so_env = 0;
     if (defined $ENV{COMMON_ENV_TOOLS}) {
     $html = '';
     @ignored_errors = ();
     %incompatibles = ();
+    %skip_modules = ();
+    %exclude_branches = ();
     $only_platform = ''; # the only platform to prepare
     $only_common = ''; # the only common output tree to delete when preparing
     %build_modes = ();
     $html_last_updated = 0;
     %jobs_hash = ();
     $html_path = undef;
-    $html_file = CorrectPath($ENV{SOLARSRC} . '/' . $ENV{INPATH}. '.build.html');
     $build_finished = 0;
+    $html_file = '';
     %had_error = (); # hack for misteriuos windows problems - try run dmake 2 times if first time there was an error
     $mkout = CorrectPath("$ENV{SOLARENV}/bin/mkout.pl");
     %weights_hash = (); # hash contains info about how many modules are dependent from one module
 
     get_options();
     
-    $html_file = CorrectPath($html_path . '/' . $ENV{INPATH}. '.build.html') if (defined $html_path);
 #    my $temp_html_file = CorrectPath($tmp_dir. '/' . $ENV{INPATH}. '.build.html');
     get_build_modes();
     %deliver_env = ();
         $deliver_env{'OUTPATH'}++;
         $deliver_env{'L10N_framework'}++;
     };
+    $StandDir = get_stand_dir();   # This also sets $initial_module
+    $source_config = SourceConfig -> new($StandDir);
+    
+    if ($html) {
+        if (defined $html_path) {
+            $html_file = CorrectPath($html_path . '/' . $ENV{INPATH}. '.build.html');
+        } else {
+            my $log_directory = Cwd::realpath(CorrectPath($StandDir . '/../log'));
+            if ((!-d $log_directory) && (!mkdir($log_directory))) {
+                print_error("Cannot create $log_directory for writing html file\n");
+            };
+            $html_file = $log_directory . '/' . $ENV{INPATH}. '.build.html';
+            print "\nPath to html status page: $html_file\n";
+        };
+    };
 
     if ($generate_config && ($clear_config || (scalar keys %remove_from_config)||(scalar keys %add_to_config))) {
         generate_config_file();
         exit 0;
     }
-    $StandDir = get_stand_dir();   # This also sets $initial_module
     get_module_and_buildlist_paths();
     provide_consistency() if (defined $ENV{CWS_WORK_STAMP} && defined($ENV{COMMON_ENV_TOOLS}));
 
 };
 
 sub generate_config_file {
-    my $source_config = SourceConfig->new();
     $source_config->add_active_modules([keys %add_to_config], 1) if (scalar %add_to_config);
     $source_config->remove_activated_modules([keys %remove_from_config], 1) if (scalar %remove_from_config);
     $source_config->remove_all_activated_modules() if ($clear_config);
 # Get dependencies hash of the current and all parent projects
 #
 sub get_parent_deps {
-    my (%parents_deps_hash, $module, $parent);
     my $prj_dir = shift;
     my $deps_hash = shift;
-    my @unresolved_parents = get_parents_array($prj_dir);
-    $parents_deps_hash{$_}++ foreach (@unresolved_parents);
-    $$deps_hash{$prj_dir} = \%parents_deps_hash;
-    while ($module = pop(@unresolved_parents)) {
+    my @unresolved_parents = ($prj_dir);
+    my %skipped_branches = ();
+    while (my $module = pop(@unresolved_parents)) {
+        next if (defined $$deps_hash{$module});
         my %parents_deps_hash = ();
-        $parents_deps_hash{$_}++ foreach (get_parents_array($module));
+        foreach (get_parents_array($module)) {
+            if (defined $exclude_branches{$_}) {
+                $skipped_branches{$_}++;
+                next;
+            };
+            $parents_deps_hash{$_}++;
+        }
         $$deps_hash{$module} = \%parents_deps_hash;
         foreach $Parent (keys %parents_deps_hash) {
-            if (!defined($$deps_hash{$Parent})) {
+            if (!defined($$deps_hash{$Parent}) && (!defined $exclude_branches{$module})) {
                 push (@unresolved_parents, $Parent);
             };
         };
     };
     check_deps_hash($deps_hash);
+    foreach (keys %skipped_branches) {
+        print $echo . "Skipping module's $_ branch\n";
+        delete $exclude_branches{$_};
+    };
+    my @missing_branches = keys %exclude_branches;
+    if (scalar @missing_branches) {
+        print_error("For $prj_dir branche(s): \"@missing_branches\" not found\n");
+    };
 };
 
 sub store_weights {
 };
 
 #
-# This procedure fills out the %reversed_dependencies hash,
-# the hash contaninig the info about modules "waiting" for the module
+# This procedure fills the second hash with reversed dependencies,
+# ie, with info about modules "waiting" for the module
 #
 sub reverse_dependensies {
-    my $deps_hash = shift;
+    my ($deps_hash, $reversed) = @_;
     foreach my $module (keys %$deps_hash) {
         foreach (keys %{$$deps_hash{$module}}) {
-            if (defined $reversed_dependencies{$_}) {
-                ${$reversed_dependencies{$_}}{$module}++
+            if (defined $$reversed{$_}) {
+                ${$$reversed{$_}}{$module}++
             } else {
                 my %single_module_dep_hash = ($module => 1);
-                $reversed_dependencies{$_} = \%single_module_dep_hash;
+                $$reversed{$_} = \%single_module_dep_hash;
             }; 
         };
     };
         };
         modules_classify(keys %global_deps_hash);
         expand_dependencies (\%global_deps_hash);
-#        prepare_build_from(\%global_deps_hash) if (scalar keys %incompatibles);
-        prepare_incompatible_build(\%global_deps_hash) if ($incompatible);
+        prepare_incompatible_build(\%global_deps_hash) if ($incompatible && (!$build_from_with_branches));
+        if ($build_from_with_branches) {
+            my %reversed_full_deps_hash = ();
+            reverse_dependensies(\%global_deps_hash, \%reversed_full_deps_hash);
+            prepare_build_from_with_branches(\%global_deps_hash, \%reversed_full_deps_hash);
+        }
         if ($build_all_cont || $build_since) {
             prepare_build_all_cont(\%global_deps_hash);
         };
                 print_error("There are modules:\n@missing_modules\n\nthat should be built, but they are not activated. Please, verify your $source_config_file.\n");
             };
         };
-        foreach my $module (%dead_parents) {
+        foreach my $module (keys %dead_parents, keys %skip_modules) {
             remove_from_dependencies($module, \%global_deps_hash);
             delete ($global_deps_hash{$module}) if (defined $global_deps_hash{$module});
         };
         store_weights(\%global_deps_hash);
         backup_deps_hash(\%global_deps_hash, \%global_deps_hash_backup);
-        reverse_dependensies(\%global_deps_hash_backup);
+        reverse_dependensies(\%global_deps_hash_backup, \%reversed_dependencies);
         $modules_number = scalar keys %global_deps_hash;
         initialize_html_info($_) foreach (keys %global_deps_hash);
         if ($processes_to_run) {
     while ($arg = pop(@dmake_args)) {
         $dmake .= ' '.$arg;
     };
+    $dmake .= ' verbose=true' if ($html);
 };
 
 #
         $ENV{mk_tmp} = '';
         die "No environment set\n";
     };
-    my $StandDir;
-    if ( defined $ENV{PWD} ) {
-	    $StandDir = $ENV{PWD};
-	} elsif (defined $ENV{_cwd}) {
-		$StandDir = $ENV{_cwd};
-	} else {
-		$StandDir = cwd();
+    my $repository_helper = RepositoryHelper->new();
+    my $StandDir = $repository_helper->get_repository_root();
+    my $initial_dir = $repository_helper->get_initial_directory();
+    if ($StandDir eq $initial_dir) {
+        print_error('Found no project to build');
     };
-    my $previous_dir = '';
-    do {
-        foreach (@possible_build_lists) {# ('build.lst', 'build.xlist');
-            if (-e $StandDir . '/prj/'.$_) {
-                $initial_module = File::Basename::basename($StandDir);
-                $build_list_paths{$initial_module} =$StandDir . '/prj/'.$_; 
-                $StandDir = File::Basename::dirname($StandDir);
-                $module_paths{$initial_module} = $StandDir . "/$initial_module";
+    $initial_module = substr($initial_dir, length($StandDir) + 1);
+    if ($initial_module =~ /\\|\//) {
+        $initial_module = File::Basename::dirname($initial_module);
+    };
+    $module_paths{$initial_module} = $StandDir . "/$initial_module";
+#    $build_list_paths{$initial_module} =$StandDir . '/prj/'.$_; 
+#    if ( defined $ENV{PWD} ) {
+#	    $StandDir = $ENV{PWD};
+#	} elsif (defined $ENV{_cwd}) {
+#		$StandDir = $ENV{_cwd};
+#	} else {
+#		$StandDir = cwd();
+#    };
+#    my $previous_dir = '';
+#    do {
+#        foreach (@possible_build_lists) {# ('build.lst', 'build.xlist');
+#            if (-e $StandDir . '/prj/'.$_) {
+#                $initial_module = File::Basename::basename($StandDir);
+#                $build_list_paths{$initial_module} =$StandDir . '/prj/'.$_; 
+#                $StandDir = File::Basename::dirname($StandDir);
+#                $module_paths{$initial_module} = $StandDir . "/$initial_module";
                 return $StandDir;
-            } elsif ($StandDir eq $previous_dir) {
-                $ENV{mk_tmp} = '';
-                print_error('Found no project to build');
-            };
-        };
-        $previous_dir = $StandDir;
-        $StandDir = File::Basename::dirname(Cwd::realpath($StandDir));
-        print_error('Found no project to build') if (!$StandDir);
-    }
-#    while (chdir '..');
-    while (chdir "$StandDir");
+#            } elsif ($StandDir eq $previous_dir) {
+#                $ENV{mk_tmp} = '';
+#                print_error('Found no project to build');
+#            };
+#        };
+#        $previous_dir = $StandDir;
+#        $StandDir = File::Basename::dirname(Cwd::realpath($StandDir));
+#        print_error('Found no project to build') if (!$StandDir);
+#    }
+#    while (chdir "$StandDir");
 };
 
 #
                     $jobs_hash{$key} = {    SHORT_NAME => $string,
                                             BUILD_NUMBER => $build_number,
                                             STATUS => 'waiting',
-                                            LOG_PATH => $module . "/$ENV{INPATH}/misc/logs/$log_name",
+                                            LOG_PATH => '../' . $source_config->get_module_repository($module) . "/$module/$ENV{INPATH}/misc/logs/$log_name",
                                             LONG_LOG_PATH => CorrectPath($module_paths{$module} . "/$ENV{INPATH}/misc/logs/$log_name"),
                                             START_TIME => 0,
                                             FINISH_TIME => 0,
 
 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] [--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 "Syntax:    build    [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches prj_name1[:prj_name2] [--skip prj_name1[:prj_name2] [prj_name3 [...]] [prj_name3 [...]|-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]]]] [--exclude_branch_from prj_name1[:prj_name2] [prj_name3 [...]]] [--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";
     print STDERR "\nSwitches:\n";
     print STDERR "        --all        - build all projects from very beginning till current one\n";
     print STDERR "        --from       - build all projects dependent from the specified (including it) till current one\n";
+    print STDERR "        --exclude_branch_from    - exclude module(s) and its branch from the build\n";
     print STDERR "        --mode OOo   - build only projects needed for OpenOffice.org\n";
     print STDERR "        --prepare    - clear all projects for incompatible build from prj_name till current one [for platform] (cws version)\n";
-    print STDERR "        --with_branches- build all projects in neighbour branches and current branch starting from actual project\n";
+    print STDERR "        --with_branches- the same as \"--from\" but with build all projects in neighbour branches\n";
+    print STDERR "        --skip       - do not build certain module(s)\n";
     print STDERR "        --since      - build all projects beginning from the specified till current one (the same as \"--all:prj_name\", but skipping prj_name)\n";
     print STDERR "        --checkmodules      - check if all required parent projects are availlable\n";
     print STDERR "        --show       - show what is going to be built\n";
         $arg =~ /^--dlv_switch$/    and $dlv_switch = shift @ARGV    and next;
         $arg =~ /^--file$/        and $cmd_file = shift @ARGV             and next;
         $arg =~ /^-F$/        and $cmd_file = shift @ARGV             and next;
+        $arg =~ /^--skip$/    and get_modules_passed(\%skip_modules)      and next;
 
-        $arg =~ /^--with_branches$/        and $build_all_parents = 1
-                                and $build_from_with_branches = shift @ARGV         and next;
-        $arg =~ /^-b$/        and $build_all_parents = 1
-                                and $build_from_with_branches = shift @ARGV         and next;
-
+        if ($arg =~ /^--with_branches$/ || $arg =~ /^-b$/) {
+                                    $build_from_with_branches = 1;
+                                    $build_all_parents = 1;
+                                    get_modules_passed(\%incompatibles);
+                                    next;
+        };
         $arg =~ /^--all:(\S+)$/ and $build_all_parents = 1
                                 and $build_all_cont = $1            and next;
         $arg =~ /^-a:(\S+)$/ and $build_all_parents = 1
                                 and $build_all_cont = $1            and next;
         if ($arg =~ /^--from$/ || $arg =~ /^-f$/) {
                                     $build_all_parents = 1;
-                                    get_incomp_projects();
+                                    get_modules_passed(\%incompatibles);
+                                    next;
+        };
+        if ($arg =~ /^--exclude_branch_from$/) {
+                                    get_modules_passed(\%exclude_branches);
                                     next;
         };
         $arg =~ /^--prepare$/    and $prepare = 1 and next;
         print_error("\"--html_path\" switch is used only with \"--html\"") if ($html_path);
         print_error("\"--dontgraboutput\" switch is used only with \"--html\"") if ($dont_grab_output);
     };
+    if ((scalar keys %exclude_branches) && !$build_all_parents) {
+        print_error("\"--exclude_branch_from\" is not applicable for one module builds!!");
+    };
     $grab_output = 0 if ($dont_grab_output);
     print_error('Switches --with_branches and --all collision') if ($build_from_with_branches && $build_all_cont);
+    print_error('Switch --skip is for building multiple modules only!!') if ((scalar keys %skip_modules) && (!$build_all_parents));
 #    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_with_branches && $build_since);
     if ($show) {
 
 sub get_module_and_buildlist_paths {
     if ($build_all_parents || $checkparents) {
-        my $source_config = SourceConfig -> new($StandDir);
         $source_config_file = $source_config->get_config_file_path();
         $active_modules{$_}++ foreach ($source_config->get_active_modules());
         my %active_modules_copy = %active_modules;
             $message_part .= "--from @broken_modules_names\n";
         };
     } else {
-        $message_part .= "--all:@broken_modules_names\n";
+        if ($processes_to_run) {
+            $message_part .= "--from ";
+        } else {
+            $message_part .= "--all:";
+        };
+        $message_part .= "@broken_modules_names\n";
+
     };
     if ($broken_modules_number && $build_all_parents) {
         print "\n";
 
 #
 # This procedure provides consistency for cws
-# and optimized build (ie in case of -with_branches, -all:prj_name
+# and optimized build (ie in case of --with_branches, -all:prj_name
 # and -since switches)
 #
 sub provide_consistency {
     check_dir();
-    foreach $var_ref (\$build_from_with_branches, \$build_all_cont, \$build_since) {
+    foreach $var_ref (\$build_all_cont, \$build_since) {
         if ($$var_ref) {
             return if (defined $module_paths{$$var_ref});
             print_error("Cannot find module '$$var_ref'", 9);
      chmod '0664', $file;
 };
 
+sub prepare_build_from_with_branches {
+    ($full_deps_hash, $reversed_full_deps_hash) = @_;
+    foreach my $prerequisite (keys %$full_deps_hash) {
+        foreach my $dependent_module (keys %incompatibles) {
+            if (defined ${$$reversed_full_deps_hash{$prerequisite}}{$dependent_module}) {
+                remove_from_dependencies($prerequisite, $full_deps_hash);
+                delete $$full_deps_hash{$prerequisite};
+#                print "Removed $prerequisite\n";
+                last;
+            };
+        };
+    };
+};
+
 #
 # Removes projects which it is not necessary to build
 # in incompatible build
         if (!defined $$deps_hash{$module}) {
             print_error("The module $initial_module is independent from $module\n");
         }
-        delete $incompatibles{$module};
         $incompatibles{$module} = $$deps_hash{$module};
         delete $$deps_hash{$module};
     }
     @modules_built = keys %$deps_hash;
     %add_to_config = %$deps_hash;
     if ($prepare) {
-        if ((!defined $ENV{UPDATER}) || (defined $ENV{CWS_WORK_STAMP})) {
-            SourceConfig->new()->add_active_modules([keys %add_to_config], 0);
+        if ((!(defined $ENV{UPDATER} && (!defined $ENV{CWS_WORK_STAMP}))) || (defined $ENV{CWS_WORK_STAMP})) {
+            $source_config->add_active_modules([keys %add_to_config], 0);
         }
         clear_delivered();
     }
 
 #
 # Removes projects which it is not necessary to build
-# with -with_branches switch
-#
-#sub prepare_build_from {
-#    my ($prj, $deps_hash);
-#    $deps_hash = shift;
-#    my %from_deps_hash = ();   # hash of dependencies of the -from project
-#    get_parent_deps($build_from_with_branches, \%from_deps_hash);
-#    foreach $prj (keys %from_deps_hash) {
-#        delete $$deps_hash{$prj};
-#        remove_from_dependencies($prj, $deps_hash);
-#    };
-#};
-
-#
-# Removes projects which it is not necessary to build
 # with --all:prj_name or --since switch
 #
 sub prepare_build_all_cont {
 #    };
 };
 
-sub get_incomp_projects {
+sub get_modules_passed {
+    my $hash_ref = shift;
     my $option = '';
     while ($option = shift @ARGV) {
         if ($option =~ /^-+/) {
                 print_error("\'--from\' switch collision") if ($build_all_cont);
                 $build_all_cont = $';
             };
-            $incompatibles{$option}++;
+            $$hash_ref{$option}++;
         };
     };
 };

solenv/bin/modules/RepositoryHelper.pm

+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+#*************************************************************************
+#
+# RepositoryHelper - Perl for working with repositories and underlying SCM 
+#
+# usage: see below
+#
+#************************************************************************* 
+
+package RepositoryHelper;
+
+use strict;
+
+
+use Carp;
+use Cwd qw (cwd);
+use File::Basename;
+#use File::Temp qw(tmpnam);
+
+my $debug = 0;
+
+#####  profiling #####
+
+##### ctor #####
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $initial_directory = shift;
+    if ($initial_directory) {
+        $initial_directory = Cwd::realpath($initial_directory);
+    } else {
+        if ( defined $ENV{PWD} ) {
+            $initial_directory = $ENV{PWD};
+        } elsif (defined $ENV{_cwd}) {
+            $initial_directory = $ENV{_cwd};
+        } else {
+            $initial_directory = cwd();
+        };
+    };
+    my $self = {};
+    $self->{INITIAL_DIRECTORY} = $initial_directory;
+    $self->{REPOSITORY_ROOT} = undef;
+    $self->{REPOSITORY_NAME} = undef;
+    $self->{SCM_NAME} = undef;
+    detect_repository($self);
+    bless($self, $class);
+    return $self;
+}
+
+##### methods #####
+sub get_repository_root 
+{   
+    my $self        = shift;
+    return $self->{REPOSITORY_ROOT};
+}
+
+sub get_initial_directory 
+{
+    my $self        = shift;
+    return $self->{INITIAL_DIRECTORY};
+}
+
+sub get_scm_name 
+{
+    my $self        = shift;
+    return$self->{SCM_NAME}; 
+}
+
+##### private methods #####
+sub search_for_hg {
+    my $self        = shift;
+    my $hg_root;
+    my $scm_name = 'hg';
+    if (open(COMMAND, "$scm_name root 2>&1 |")) {
+        foreach (<COMMAND>) {
+            next if (/^Not trusting file/);
+            chomp;
+            $hg_root = $_;
+            last;
+        };
+        close COMMAND;
+        chomp $hg_root;
+        if ($hg_root !~ /There is no Mercurial repository here/) {
+            $self->{REPOSITORY_ROOT} = $hg_root;
+            $self->{SCM_NAME} = $scm_name;
+            return 1;
+        };
+    };
+    return 0;
+};
+
+sub search_via_build_lst {
+    my $self = shift;
+    my @possible_build_lists = ('build.lst', 'build.xlist'); # build lists names
+    my $previous_dir = '';
+    my $rep_root_candidate = $self->{INITIAL_DIRECTORY};
+    do {
+        foreach (@possible_build_lists) {# ('build.lst', 'build.xlist');
+            if (-e $rep_root_candidate . '/prj/'.$_) {
+                $self->{REPOSITORY_ROOT} = File::Basename::dirname($rep_root_candidate);
+                return 1;
+            } elsif ($rep_root_candidate eq $previous_dir) {
+                return 0;
+            };
+        };
+        $previous_dir = $rep_root_candidate;
+        $rep_root_candidate = File::Basename::dirname(Cwd::realpath($rep_root_candidate));
+        return 0 if (!$rep_root_candidate);
+    }
+    while (chdir "$rep_root_candidate");
+};
+
+sub detect_repository {
+    my $self        = shift;
+    return if (search_via_build_lst($self));
+    chdir $self->{INITIAL_DIRECTORY};
+    return if (search_for_hg($self));
+    croak('Cannot determine source directory/repository for ' . $self->{INITIAL_DIRECTORY});
+};
+
+##### finish #####
+
+1; # needed by use or require
+
+__END__
+
+=head1 NAME
+
+RepositoryHelper - Perl module for working with repositories and underlying SCM
+
+=head1 SYNOPSIS
+
+    # example that will analyze sources and return the source root directory
+
+    use RepositoryHelper;
+
+    # Create a new instance:
+    $a = RepositoryHelper->new();
+
+    # Get repositories for the actual workspace:
+    $a->get_repository_root();
+
+  
+=head1 DESCRIPTION
+
+RepositoryHelper is a perlPerl module for working with repositories and underlying SCM 
+in the database.
+
+Methods:
+
+RepositoryHelper::new()
+
+Creates a new instance of RepositoryHelper. Can be initialized by: some path which likely to belong to a repository, default - empty, the current dir will be taken.
+
+RepositoryHelper::get_repository_root()
+
+Returns the repository root, retrieved by SCM methods or on educated guess...
+
+RepositoryHelper::get_initial_directory()
+
+Returns full path to the initialistion directory.
+
+=head2 EXPORT
+
+RepositoryHelper::new()
+RepositoryHelper::get_repository_root()
+RepositoryHelper::get_scm_name()
+RepositoryHelper::get_initial_directory()
+
+=head1 AUTHOR
+
+Vladimir Glazunov, vg@openoffice.org
+
+=head1 SEE ALSO
+
+perl(1).
+
+=cut

solenv/bin/modules/SourceConfig.pm

 use strict;
 
 use constant SOURCE_CONFIG_FILE_NAME => 'source_config'; 
-use constant SOURCE_CONFIG_VERSION => 2; 
+use constant SOURCE_CONFIG_VERSION => 3; 
 
 use Carp;
 use Cwd;
+use RepositoryHelper;
 use File::Basename;
 use File::Temp qw(tmpnam);
 
             $source_root .= '/..';
         }
     } else {
-        $source_root = Cwd::realpath($ENV{SOURCE_ROOT_DIR});
+        $source_root = $ENV{SOURCE_ROOT_DIR};
     };
+    $source_root = Cwd::realpath($source_root);
     $self->{SOURCE_ROOT} = $source_root;
     $self->{DEBUG} = 0;
     $self->{VERBOSE} = 0;
     $self->{WARNINGS} = [];
     $self->{REPORT_MESSAGES} = [];
     $self->{CONFIG_FILE_CONTENT} = [];
-    $self->{DEFAULT_REPOSITORY} = undef;
     if (defined $self->{USER_SOURCE_ROOT}) {
         ${$self->{REPOSITORIES}}{File::Basename::basename($self->{USER_SOURCE_ROOT})} = $self->{USER_SOURCE_ROOT};
-        $self->{DEFAULT_REPOSITORY} = File::Basename::basename($self->{USER_SOURCE_ROOT});
     };
     $self->{SOURCE_CONFIG_FILE} = get_config_file($self->{SOURCE_ROOT}) if (!defined $self->{SOURCE_CONFIG_FILE});
     $self->{SOURCE_CONFIG_DEFAULT} = $self->{SOURCE_ROOT} .'/'.SOURCE_CONFIG_FILE_NAME;
+    if (defined $self->{USER_SOURCE_ROOT}) {
+        ${$self->{REPOSITORIES}}{File::Basename::basename($self->{USER_SOURCE_ROOT})} = $self->{USER_SOURCE_ROOT};
+    };
     read_config_file($self);
+   	get_module_paths($self);
     bless($self, $class);
     return $self;
 }
     return sort keys %{$self->{REPOSITORIES}};
 }
 
+sub add_repository 
+{   
+    my $self        = shift;
+    my $new_rep_path = shift;
+    $new_rep_path = Cwd::realpath($new_rep_path);
+    my $new_rep_name = File::Basename::basename($new_rep_path);
+    if (defined ${$self->{REPOSITORIES}}{$new_rep_name}) {
+        croak("Repository $new_rep_name is already defined!!");
+    };
+    ${$self->{REPOSITORIES}}{$new_rep_name} = $new_rep_path;
+    $self -> get_repository_module_paths($new_rep_name);
+}
+
 sub get_config_file_default_path {
     my $self        = shift;
     return $self->{SOURCE_CONFIG_DEFAULT};
 sub get_module_repository {
     my $self = shift;
     my $module = shift;
-    $self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
     if (defined ${$self->{MODULE_REPOSITORY}}{$module}) {
         return ${$self->{MODULE_REPOSITORY}}{$module};
     } else {
 sub get_module_path {
     my $self = shift;
     my $module = shift;
-    $self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
     if (defined ${$self->{MODULE_PATHS}}{$module}) {
         return ${$self->{MODULE_PATHS}}{$module};
     } else {
 sub get_module_build_list {
     my $self = shift;
     my $module = shift;
-    $self -> get_buildlist_paths() if (!scalar keys %{$self->{MODULE_BUILD_LIST_PATHS}});
     if (defined ${$self->{MODULE_BUILD_LIST_PATHS}}{$module}) {
         return ${$self->{MODULE_BUILD_LIST_PATHS}}{$module};
     } else {
+        my @possible_build_lists = ('build.lst', 'build.xlist'); # build lists names
+        foreach (@possible_build_lists) {
+            my $possible_path = ${$self->{MODULE_PATHS}}{$module} . "/prj/$_";
+            if (-e $possible_path) {
+                ${$self->{MODULE_BUILD_LIST_PATHS}}{$module} = $possible_path;
+                return $possible_path;
+            };
+        };
         Carp::cluck("No build list in module $module found!!\n") if ($self->{DEBUG});
         return undef;
     };
 {   
     my $self = shift;
     my $module = shift;
-    $self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
     return sort keys %{$self->{MODULE_PATHS}};
 };
 
     if (scalar keys %{$self->{ACTIVATED_MODULES}}) {
         return sort keys %{$self->{ACTIVATED_MODULES}};
 	}
-    $self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
    	return sort keys %{$self->{REAL_MODULES}};
 }
 
     if (scalar keys %{$self->{ACTIVATED_MODULES}}) {
         return exists ($self->{ACTIVATED_MODULES}{$module});
 	}
-   	$self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
     return exists ($self->{REAL_MODULES}{$module});
 }
 
 ##### private methods #####
 
-sub get_buildlist_paths {
+sub get_repository_module_paths {
     my $self        = shift;
-    $self -> get_module_paths() if (!scalar keys %{$self->{MODULE_PATHS}});
-    my @possible_build_lists = ('build.lst', 'build.xlist'); # build lists names
-    foreach my $module (keys %{$self->{MODULE_PATHS}}) {
-        foreach (@possible_build_lists) {
-            my $possible_path = ${$self->{MODULE_PATHS}}{$module} . "/prj/$_";
-            ${$self->{MODULE_BUILD_LIST_PATHS}}{$module} = $possible_path if (-e $possible_path);
+    my $repository        = shift;
+    my $repository_path = ${$self->{REPOSITORIES}}{$repository};
+    if (opendir DIRHANDLE, $repository_path) {
+        foreach my $module (readdir(DIRHANDLE)) {
+            next if (($module =~ /^\.+/) || (!-d "$repository_path/$module"));
+            my $module_entry = $module;
+            if (($module !~ s/\.lnk$//) && ($module !~ s/\.link$//)) {
+                $self->{REAL_MODULES}{$module}++;
+            }
+            my $possible_path = "$repository_path/$module_entry";
+            if (-d $possible_path) {
+                if (defined ${$self->{MODULE_PATHS}}{$module}) {
+                    close DIRHANDLE;
+                    croak("Ambiguous paths for module $module: $possible_path and " . ${$self->{MODULE_PATHS}}{$module});
+                };
+                ${$self->{MODULE_PATHS}}{$module} = $possible_path;
+                ${$self->{MODULE_REPOSITORY}}{$module} = $repository;
+            }
         };
+        close DIRHANDLE;
+    } else {
+        croak("Cannot read $repository_path repository content");
     };
 };
 
 sub get_module_paths {
     my $self        = shift;
     foreach my $repository (keys %{$self->{REPOSITORIES}}) {
-        my $repository_path = ${$self->{REPOSITORIES}}{$repository};
-        if (opendir DIRHANDLE, $repository_path) {
-            foreach my $module (readdir(DIRHANDLE)) {
-                next if (($module =~ /^\.+/) || (!-d "$repository_path/$module"));
-                my $module_entry = $module;
-                if (($module !~ s/\.lnk$//) && ($module !~ s/\.link$//)) {
-                    $self->{REAL_MODULES}{$module}++;
-                }
-                my $possible_path = "$repository_path/$module_entry";
-                if (-d $possible_path) {
-                    if (defined ${$self->{MODULE_PATHS}}{$module}) {
-                        close DIRHANDLE;
-                        croak("Ambiguous paths for module $module: $possible_path and " . ${$self->{MODULE_PATHS}}{$module});
-                    };
-                    ${$self->{MODULE_PATHS}}{$module} = $possible_path;
-                    ${$self->{MODULE_REPOSITORY}}{$module} = $repository;
-                }
-            };
-            close DIRHANDLE;
-        } else {
-            croak("Cannot read $_ repository content");
-        };
+        get_repository_module_paths($self, $repository);
     };
     my @false_actives = ();
     foreach (keys %{$self->{ACTIVATED_MODULES}}) {
     return '';
 };
 
-sub get_hg_root {
+#
+# Fallback - fallback repository is based on RepositoryHelper educated guess
+#
+sub get_fallback_repository {
     my $self = shift;
-    return $self->{USER_SOURCE_ROOT} if (defined $self->{USER_SOURCE_ROOT});
-    my $hg_root;
-    if (open(COMMAND, "hg root 2>&1 |")) {
-        foreach (<COMMAND>) {
-            next if (/^Not trusting file/);
-            chomp;
-            $hg_root = $_;
-            last;
-        };
-        close COMMAND;
-        chomp $hg_root;
-        if ($hg_root !~ /There is no Mercurial repository here/) {
-            return $hg_root;
-        };
-    };
-    croak('Cannot open find source_config and/or determine hg root directory for ' . cwd());
+    my $repository_root = RepositoryHelper->new()->get_repository_root();
+    ${$self->{REPOSITORIES}}{File::Basename::basename($repository_root)} = $repository_root;
 };
 
 sub read_config_file {
     my $self = shift;
     if (!$self->{SOURCE_CONFIG_FILE}) {
-        my $repository_root = get_hg_root($self);
-        ${$self->{REPOSITORIES}}{File::Basename::basename($repository_root)} = $repository_root;
+        if (!defined $self->{USER_SOURCE_ROOT}) {
+            get_fallback_repository($self);
+        };
         return;
     };
     my $repository_section = 0;
                     my $repository_source_path = $self->{SOURCE_ROOT} . "/$1";
                     if (defined $ENV{UPDMINOREXT}) {
                         $repository_source_path .= $ENV{UPDMINOREXT};
-                    };
-                    if ((defined $self->{DEFAULT_REPOSITORY}) && (${$self->{REPOSITORIES}}{$self->{DEFAULT_REPOSITORY}} eq $repository_source_path)) {
-                        delete ${$self->{REPOSITORIES}}{$self->{DEFAULT_REPOSITORY}};
-                        $self->{DEFAULT_REPOSITORY} = undef;
-                        
+                        if (defined ${$self->{REPOSITORIES}}{$1.$ENV{UPDMINOREXT}}) {
+                            delete ${$self->{REPOSITORIES}}{$1.$ENV{UPDMINOREXT}};
+                        };
                     };
                     ${$self->{REPOSITORIES}}{$1} = $repository_source_path;
                     ${$self->{ACTIVATED_REPOSITORIES}}{$1}++;
         };
         close SOURCE_CONFIG_FILE;
         if (!scalar keys %{$self->{REPOSITORIES}}) {
-            # Fallback - default repository is the directory where is our module...
-            my $hg_root = get_hg_root($self);
-            ${$self->{REPOSITORIES}}{File::Basename::basename($hg_root)} = $hg_root;
+            get_fallback_repository($self);
         };
     } else {
         croak('Cannot open ' . $self->{SOURCE_CONFIG_FILE} . 'for reading');
 sub add_active_repositories {
     my $self = shift;
     $self->{NEW_REPOSITORIES} = shift;
-    croak('Empty module list passed for adding to source_config') if (!scalar @{$self->{NEW_REPOSITORIES}});
+    croak('Empty repository list passed for addition to source_config') if (!scalar @{$self->{NEW_REPOSITORIES}});
     $self->{VERBOSE} = shift;
+    foreach (@{$self->{NEW_REPOSITORIES}}) {
+        $self->add_repository($_);
+    };
     generate_config_file($self);
 };
 
 sub add_active_modules {
     my $self = shift;
     $self->{NEW_MODULES} = shift;
-    croak('Empty module list passed for adding to source_config') if (!scalar @{$self->{NEW_MODULES}});
+    croak('Empty module list passed for addition to source_config') if (!scalar @{$self->{NEW_MODULES}});
     $self->{VERBOSE} = shift;
     generate_config_file($self);
 };
     # Get repositories for the actual workspace:
     $a->get_repositories();
 
+    # Add a repository new_repository for the actual workspace (via full path):
+    $a->add_repository(/DEV300/new_repository);
   
 =head1 DESCRIPTION
 
 Returns sorted list of active repositories for the actual workspace
 
 
+SourceConfig::add_repository(REPOSITORY_PATH)
+
+Adds a repository to the list of active repositories
+
+
 SourceConfig::get_active_modules()
 
 Returns a sorted list of active modules
 SourceConfig::new()
 SourceConfig::get_version()
 SourceConfig::get_repositories()
+SourceConfig::add_repository()
 SourceConfig::get_active_modules()
 SourceConfig::get_all_modules()
 SourceConfig::get_module_path($module)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.