Merge feature-block-in-context
authorJan Vrany <jan.vrany@fit.cvut.cz>
Sat, 31 Dec 2016 22:47:53 +0000
branchfeature-block-in-context
changeset 159 cbc152f322a8
parent 99 394937f3f608 (current diff)
parent 113 619c575b39da (diff)
child 160 95149f95cb5c
Merge
specs/stx-jv.rbspec
--- a/Jenkinsfile	Tue Dec 06 21:32:24 2016 +0000
+++ b/Jenkinsfile	Sat Dec 31 22:47:53 2016 +0000
@@ -4,6 +4,15 @@
 
 def pipeline;
 
+/*
+ * A helper function to return a branch to build.
+ *
+ * For normal jobs this is the value of 'Branch' field from SCM configuration.
+ * For multibranch jobs, this is the value of BRANCH_NAME environment variable.
+ *
+ * This is the same as build() function in `pipeline.groovy` and should be kept
+ * in sync. We cannot use the one there as we yet have to load it.
+ */
 def branch() {
     if (env.BRANCH_NAME == null) {
         return scm.getBranch();
@@ -35,5 +44,19 @@
     }
 }
 
-pipeline.build()
-pipeline.test()
\ No newline at end of file
+/*
+ * Set the branch to build to make sure it's in sync
+ */
+pipeline.branch = branch()
+
+/*
+ * If we're building a 'default' branch, run "integration" pipeline. Otherwise,
+ * run normal "build" pipeline, assuming this build is just a test build for
+ * some feature-in-progress. If different logic is needed, then make a branch
+ * and modify this file
+ */
+if ( branch().equals("default") ) {
+    pipeline.integration()
+} else {
+    pipeline.build()
+}
--- a/pipeline.groovy	Tue Dec 06 21:32:24 2016 +0000
+++ b/pipeline.groovy	Sat Dec 31 22:47:53 2016 +0000
@@ -10,15 +10,56 @@
  *    configurations, archive artifacts and push staged changes to opstream.
  */
 
+import com.cloudbees.plugins.credentials.CredentialsProvider;
+import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
+import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
 
-/*
- * Supported configurations
+/**
+ * Supported configurations. To overwrite, do:
+ *
+ *     ...
+ *     pipeline = load "pipeline.groovy"
+ *     ...
+ *     pipeline.configurations = [ 'NODE': 'qnx', 'ARCH' : 'mips' ]
+ *     ...
+ *
+ * Default value: see below.
  */
 configurations = [
     'NODE': ['windows' , 'linux' ],
     'ARCH': ['i386', 'x86_64' ]
 ]
 
+/** Branch to build. To overwrite do:
+ *
+ *     ...
+ *     pipeline = load "pipeline.groovy"
+ *     ...
+ *     pipeline.branch = "issue-123"
+ *     ...
+ *
+ * Default value:
+ * For multibranch jobs, this is the value of BRANCH_NAME environment variable.
+ * For normal jobs this is the value of 'Branch' field from SCM configuration.
+ *
+ * Due to Jenkins internals, the fallback to use SCM configuration must be done
+ * by 'user' of this variable (i.e., use `branch != null ? branch : scm.getBranch())
+ */
+branch = env.BRANCH_NAME
+
+/**
+ * Workspace to use. To overwrite do:
+ *
+ *     ...
+ *     pipeline = load "pipeline.groovy"
+ *     ...
+ *     pipeline.workspace = "some-other-job"
+ *     ...
+ *
+ * Default value:
+ * Name of current job.
+ */
+workspace = env.JOB_NAME
 
 /*
  * "Default" pipeline:
@@ -30,11 +71,11 @@
                 sshagent([ scm.getCredentialsId() ]) {
                     sh  """
                         if [ -f Jenkinsfile.rb ]; then
-                            hg pull ${scm.getSource()}
+                            hg pull --ssh ssh ${scm.getSource()}
                         else
-                            hg clone ${scm.getSource()} .
+                            hg clone --ssh ssh ${scm.getSource()} .
                         fi
-                        hg up ${branch()}
+                        hg up ${branch != null ? branch : scm.getBranch()}
                         """
                     sh  "ruby Jenkinsfile.rb --project \"stx:jv-branch\" --arch ${env.ARCH}  update"
                 }
@@ -45,9 +86,7 @@
             }
         }
     }
-}
 
-def test() {
     stage ( "Test" ) {
         matrix ( configurations ) {
             stage ( "Test - {${env.NODE}-${env.ARCH}}") {
@@ -67,11 +106,12 @@
      * If a single test fails, abort the pipeline. There's no point
      * archiving a broken build.
      */
+    println "Smalltalk/X built, job status is: ${currentBuild.result}"
     if (currentBuild.result == 'UNSTABLE') {
         return;
     }
     artifacts()
-    push_to_upstream()
+    push()
 }
 
 def combine(configurations, axes = null, axis = 0, partial = new HashMap(), combinations = []) {
@@ -105,7 +145,7 @@
                     newEnv.add("${k}=${conf[k]}")
                 }
                 withEnv ( newEnv ) {
-                    ws ("workspace/${env.JOB_NAME}/${env.ARCH}") {
+                    ws ("workspace/${workspace}/${env.ARCH}") {
                         block()
                     }
                 }
@@ -129,7 +169,7 @@
             newEnv.add("${k}=${conf[k]}")
         }
         withEnv ( newEnv ) {
-            ws ("workspace/${env.JOB_NAME}/${env.ARCH}") {
+            ws ("workspace/${workspace}/${env.ARCH}") {
                 block()
             }
         }
@@ -146,31 +186,58 @@
     }
 }
 
-def push_to_upstream() {
+/**
+ * Push changes to upstream reporitory. To be called after a successful
+ * build. See #build()
+ */
+def push() {
     any ( configurations ) {
-        withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: '1c40eb8f-c7ff-4ef7-8fc8-96aa6310907c', passwordVariable: 'pass', usernameVariable: 'user']]) {
-            sh "rake \"workflow:push-upstream[${user}, ${pass}]\""
+        stage ( "Push to upstream" ) {
+            /*
+             * Kludge: This stage may push changes to public BitBucket
+             * repositories. To access repos on BitBucket, I (JV) don't
+             * want to use the same key / password as for checkouts from
+             * staging repositories,
+             *
+             * Therefore, also look for another credentials with ID
+             * `workflow:push-upstream`. If it exists, then use these to
+             * push to upstrem repository. If no such credentials exist,
+             * use standard credentials.
+             *
+             * So, here we go:
+             */
+            def id1 = "workflow:push-upstream";
+            def id2 = scm.getCredentialsId();
+            def credentials = null;
+
+            for (StandardUsernameCredentials c : CredentialsProvider.lookupCredentials(StandardUsernameCredentials.class)) {
+              if (c.getId().equals(id1)) {
+                credentials = c;
+                break;
+              }
+            }
+            if (credentials == null) {
+              for (StandardUsernameCredentials c : CredentialsProvider.lookupCredentials(StandardUsernameCredentials.class)) {
+                if (c.getId().equals(id2)) {
+                  credentials = c;
+                  break;
+                }
+              }
+            }
+
+            println "Using credentials ${credentials.getId()}: ${credentials.getDescription()}"
+
+            if (credentials instanceof SSHUserPrivateKey) {
+                sshagent([ credentials.getId() ]) {
+                    sh "rake \"workflow:push-upstream\""
+                }
+            } else {
+                withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: credentials.getId(), passwordVariable: 'pass', usernameVariable: 'user']]) {
+                    sh "rake \"workflow:push-upstream[${user}, ${pass}]\""
+                }
+            }
         }
     }
 }
 
-/*
- * A helper function to return a currently used Rakefiles
- * branch.
- *
- * For normal jobs this is the value of 'Branch'
- * field from SCM configuration.
- *
- * For multibranch jobs, this is the value of BRANCH_NAME environment
- * variable.
- */
-def branch() {
-    if (env.BRANCH_NAME == null) {
-        return scm.getBranch();
-    } else {
-        return env.BRANCH_NAME;
-    }
-}
-
-
 return this;
--- a/rakelib/checkout.rake	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/checkout.rake	Sat Dec 31 22:47:53 2016 +0000
@@ -59,8 +59,7 @@
         doit = true
       elsif (pkg.property_defined? :repository) and (pkg.repository != pkg.parent_package.repository)
         # doit = true        
-      end 
-      
+      end      
     end
 
     if doit
--- a/rakelib/compile.rake	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/compile.rake	Sat Dec 31 22:47:53 2016 +0000
@@ -23,7 +23,7 @@
 # avoid sources to leak (for exaple, due to a bug in packaging scripts).
 # Unathorized subjects should not be able to checkout sources in first instance.
 def should_remove_librun_and_stc_sources
-    return ! (core_developer? or ENV['RETAIN_STX_AND_LIBRUN_SOURCE'] = 'yespleaseretain!')
+    return ! (core_developer? or ENV['RETAIN_STX_AND_LIBRUN_SOURCE'] == 'yespleaseretain!')
 end
 
 def rm_rf_all_in_except(directory, exceptions = [])
@@ -304,7 +304,7 @@
 
   rule 'makefile' do | t |
     if File.exist?(File.dirname(t.name) / 'GNUmakefile')
-  rm (File.dirname(t.name) / 'GNUmakefile')
+      rm (File.dirname(t.name) / 'GNUmakefile')
     end
 
     chdir File.dirname(t.name) do
@@ -350,6 +350,13 @@
                 mkdir 'libffi' / 'build_win32' / 'objbc'
               end
             end
+          # A workaround for Windows 10 & ancient Borland make which 
+          # tend to crash there when trying to recompile already compiled
+          # librun. Sigh, we have to move away from it as soon as possible!
+          
+          if win32? and (File.exist? 'stxmain.c') then
+            touch "stxmain.c"
+          end
           make
           cleanup_librun()
         rescue Exception => e
@@ -384,61 +391,19 @@
       end
     end
   end
-  
-  if win32? and TOOLCHAIN == 'bcc'
-    libbc = STX_TOP_DIR / 'lib' / 'bc'
-
-    task :'libraries' => [  libbc / 'cs32i.lib' ,
-            libbc / 'stxc32i.lib' ,
-            libbc / 'X11omf.lib' ,
-            libbc / 'Xextomf.lib' ,
-            STX_TOP_DIR / 'support' / 'zlib-1.2.3' / 'objbc' / 'zlib.lib'
-         ]
-
-    file libbc / 'cs32i.lib' => libbc do | t |
-      cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
-    end
-
-    file libbc / 'stxc32i.lib' => libbc do | t |
-    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
-    end
-
-    file libbc / 'X11omf.lib' => libbc do | t |
-    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
-    end
-
-
-    file libbc / 'Xextomf.lib' => libbc do | t |
-    cp STX_TOP_DIR / 'support' / 'win32' /  'borland' / (File.basename(t.name)), libbc
-    end
-
-    directory libbc
-
-    file STX_TOP_DIR / 'support' / 'zlib-1.2.3' / 'objbc' / 'zlib.lib' do
-      chdir STX_TOP_DIR / 'support' / 'zlib-1.2.3' do
-        make
-      end
-    end
-
-  end
-
 end
 
 
-if unix?
-    #task :'stx:libview2:pre' => STX_TOP_DIR / 'support' / 'libjpeg-7' / 'libjpeg.a'
+#
+# Various compilation hacks here and there (sigh)
+# 
 
-    #file STX_TOP_DIR / 'support' / 'libjpeg-7/libjpeg.a' => STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a' do
-    #    cp STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a',
-    #        STX_TOP_DIR / 'support' / 'libjpeg-7' / 'libjpeg.a'
-    #end
-    #
-    #file STX_TOP_DIR / 'support' / 'libjpeg-7' / '.libs' / 'libjpeg.a' do
-    #    chdir STX_TOP_DIR / 'libview2' do
-    #        make '../support/libjpeg-7/.libs/libjpeg.a'
-    #    end
-    #end
-
+if unix?
+  # A hack for Debian (and possibly other Linux distros) that does not ship
+  # 32bit libodbc.a / libodbcinst.a. Link directly against .so
+  task :'stx:libdb/libodbc:pre' do     
+	  sed('-lodbc -lodbcinst' , '-l:libodbc.so.2 -l:libodbcinst.so.2', BUILD_DIR / 'stx' / 'libdb' / 'libodbc' / 'Make.proto', true)
+  end  
 end
 
 
--- a/rakelib/dist-jv.rake	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/dist-jv.rake	Sat Dec 31 22:47:53 2016 +0000
@@ -103,6 +103,7 @@
       install BUILD_DIR / 'stx' / 'projects' / 'smalltalk' / rc_file, rc_dir
     end
     install BUILD_DIR / 'stx' / 'projects' / 'smalltalk'/ '*.wsp' , lib_dir
+    install BUILD_DIR / 'stx' / 'projects' / 'smalltalk'/ 'rc.d' / '*' , lib_dir / 'rc.d'
 
     case
     when win32?
@@ -144,7 +145,9 @@
       #end
       install   BUILD_DIR / pkg.directory / '*.st' ,         pkg_dir / pkg.directory
       install   BUILD_DIR / pkg.directory / 'abbrev.stc' ,   pkg_dir / pkg.directory if File.exist? BUILD_DIR / pkg.directory / 'abbrev.stc'
-      install   BUILD_DIR / pkg.directory / '*.so' ,         pkg_dir / pkg.directory
+      if File.exist? BUILD_DIR / pkg.directory / pkg.dll_name then
+        install   BUILD_DIR / pkg.directory / '*.so',         pkg_dir / pkg.directory
+      end
       ['resources' , 'bitmaps' , 'styles', 'java' ].each do | subdir |
         if File.exist? BUILD_DIR / pkg.directory / subdir
           cp_rx BUILD_DIR / pkg.directory / subdir ,    pkg_dir / pkg.directory do | fname |
--- a/rakelib/dsl.rb	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/dsl.rb	Sat Dec 31 22:47:53 2016 +0000
@@ -50,7 +50,7 @@
     def self.property(name, properties = {})      
       @property_definitions ||= {}
       if @property_definitions.include? name
-        raise Exception.new("Property #{name} already defined in class #{self.name}")
+        raise Exception.new("Property #{name} already defined for this kind of object")
       else
         prop_def_class = properties[:property_definition_class] || PropertyDefinition
         @property_definitions[name] = prop_def_class.new(name, self, properties)
--- a/rakelib/hglib.rb	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/hglib.rb	Sat Dec 31 22:47:53 2016 +0000
@@ -269,7 +269,7 @@
     # If `noupdate` is true, working copy is not updated, i.e., will be
     # empty. Use this when you're going to issue `update(rev)` shortly after.
     #
-    def self.clone(uri, directory, noupdate: false)
+    def self.clone(uri, directory, noupdate: false, publishing: false)
       uri_obj = URI(uri)
       host = uri_obj.host
       scheme = uri_obj.scheme
@@ -278,11 +278,8 @@
       # these days) amd saves some CPU cycles.
       local = HG::Repository::host_on_lan?(URI(uri).host)
       ssh = HG::Repository::sshconf(uri)      
-      if noupdate then
-        HG::hg("clone", uri, directory, ssh: ssh, uncompressed: local, noupdate: true)
-      else
-        HG::hg("clone", uri, directory, ssh: ssh, uncompressed: local)
-      end
+      
+      HG::hg("clone", uri, directory, ssh: ssh, uncompressed: local, noupdate: noupdate, config: "phases.publish=#{publishing}")
       return HG::Repository.new(directory)
     end
 
--- a/rakelib/rbspec.rb	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/rbspec.rb	Sat Dec 31 22:47:53 2016 +0000
@@ -380,11 +380,23 @@
     end
 
     def dll_name_without_suffix()
-      return "lib#{self.directory.gsub(File::SEPARATOR, "_")}"
+      # Sigh, a special hack for stx:librun which is NOT
+      # libstx_librun.so/fll but just librun.so / librun.dll      
+      # and for STC which  produces no .so / .dll
+      case self.name
+      when 'stx:stc'
+        return nil
+      when 'stx:librun'
+        return 'librun'
+      else
+        return "lib#{self.directory.gsub(File::SEPARATOR, "_")}"
+      end
     end
     
     def dll_name()
-      case 
+      case
+      when self.name == 'stx:stc' 
+        return nil      
       when win32?
         return  "#{dll_name_without_suffix()}.dll"
       when unix?
@@ -432,11 +444,16 @@
       if not (mandatory or referenced) then
         raise Exception.new("Nor mandator nor referenced prereqs asked. Must specify either `mandatoryy: true` or `referenced: true` or both")
       end
+
       # Special hack for stx:stc and stx:librun which are actually 
       # not a smalltalk packages. 
-      if @name == 'stx:stc' or @name == 'stx:librun' then
+      if @name == 'stx:stc'      
         return []
       end
+      if @name == 'stx:librun'
+        # stx:librun depends on STC
+        return ['stx:stc']
+      end
 
       root = BUILD_DIR if (not root && defined? BUILD_DIR)
       if not root then
@@ -452,7 +469,8 @@
         source << line
       end      
       source.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
-      prereqs = []      
+      # All packaged depends on STC - one cannot compile them without it!
+      prereqs = ['stx:stc']       
       if mandatory then        
         prereqs += source.scan(/^mandatoryPreRequisites(.*?)!$/m).flatten.to_s.scan(/#'([^']+)'/).flatten
       end
--- a/rakelib/scm.rb	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/scm.rb	Sat Dec 31 22:47:53 2016 +0000
@@ -158,10 +158,7 @@
         paths['canonical'] = "#{repository.canonical}/#{directory.gsub('/', separator)}"
         hg.paths = paths
       end
-      hg.pull('default')
-      if paths['default'] != paths['canonical'] then
-        hg.pull('canonical')
-      end
+      hg.pull('canonical')
       # If revision is not specified, then look for an active bookmark
       # and update to it. If no bookmark is active, then look for bookmark
       # `master`. If it exist, then update to `master`. If it 
@@ -258,7 +255,12 @@
     separator = kwargs[:separator] || '.'
     revision =  kwargs[:revision] 
     
-    paths = { 'canonical' => "#{repository.canonical}/#{directory.gsub('/', separator)}" }            
+    paths = {}
+    if repository.canonical then
+      paths['canonical'] = "#{repository.canonical}/#{directory.gsub('/', separator)}"
+    else
+      raise Exception.new("Repository named #{repository.name} does not define mandatory canonical repository URL")
+    end
     if repository.upstream then
       paths['upstream'] = "#{repository.upstream}/#{directory.gsub('/', separator)}"
     end
@@ -266,7 +268,6 @@
       paths['staging'] = "#{repository.staging}/#{directory.gsub('/', separator)}"
     end
 
-    
     begin
       if repository.staging then
         paths['default'] = paths['staging']
@@ -280,6 +281,7 @@
         hg.paths = paths
         hg.pull('canonical')
       else
+        paths['default'] = paths['canonical']
         hg = HG::Repository.clone(paths['canonical'], root / directory, noupdate: true)
         hg.paths = paths
       end
--- a/rakelib/setup.rake	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/setup.rake	Sat Dec 31 22:47:53 2016 +0000
@@ -5,10 +5,6 @@
 defined? TMP_DIR or TMP_DIR = 'tmp'
 defined? DEBUG or DEBUG = nil
 
-if win32?
-  ENV['BCB'] = 'C:\\Borland\\BCC55' if not ENV['BCB']
-end
-
 if File.exist? 'config.rb'
   load 'config.rb'
 end
@@ -52,6 +48,10 @@
   end
 end
 
+if not defined? REPOSITORYSET
+  REPOSITORYSET = (ENV['REPOSITORYSET'] || 'default')
+end
+
 if not File.exist? 'config.rb'
   if defined? PROJECT
     File.open('config.rb', 'w') do | f |
@@ -67,12 +67,10 @@
 COMMENT
       f.puts "PROJECT='#{PROJECT}' if not defined? PROJECT"
       f.puts "ARCH='#{ARCH}' if not defined? ARCH"
+      f.puts "REPOSITORYSET='#{REPOSITORYSET}' if not defined? REPOSITORYSET"
       if defined? PROJECT_DIRS
         f.puts "PROJECT_DIRS='#{PROJECT_DIRS}' if not defined? PROJECT_DIRS"
       end
-      if defined? REPOSITORYSET
-        f.puts "REPOSITORYSET='#{REPOSITORYSET}' if not defined? REPOSITORYSET"
-      end
     end
   end
 end
@@ -152,9 +150,9 @@
 end
 
 task :'setup:dependencies' => :'checkout' do
-  project.packages.each do | pkg |        
-    if File.exist? (BUILD_DIR / pkg.directory() / pkg.project_definition_file_name()) then
-	  if not pkg.test_package? then
+  project.packages.each do | pkg |          
+    if pkg.name == 'stx:stc' or pkg.name == 'stx:librun' or File.exist? (BUILD_DIR / pkg.directory() / pkg.project_definition_file_name()) then
+	    if not pkg.test_package? then
         task "#{project.application.name}:dependencies" => pkg.name
         task "#{pkg.name}:dependencies" => pkg.prereqs(mandatory: true)
       end
@@ -233,7 +231,7 @@
         link_libobjs=''
         project.packages.each do | p |
           if File.exist? (BUILD_DIR / p.directory() / p.project_definition_file_name()) then
-            if not p.application? and p.link              
+            if not p.application? and p.link and not p.test_package?
               liblist += "#{p.dll_name_without_suffix()} "
               libobjs += "#{File.join(pkg.top() , p.directory(), p.dll_name())} "
               link_libobjs += "#{p.dll_name()} "                
@@ -262,12 +260,33 @@
         if pkg.application? and win32?
           make 'exe'
           make 'RESOURCEFILES'
-        else
-          # Somewhat stupid detection whether we run recent St/X or not...
-          if File.exist? BUILD_DIR / 'stx' / 'libbasic2' / 'Makefile.init'
-            make "#{make_vars} full"
+        else          
+          if pkg.name == 'stx:stc' 
+            # Sigh, on UNIX makefile is generated. So if we're using
+            # binary stc, we have to recreate it first.
+            if unix? then
+              if not File.exist? 'makefile'
+                sh "'#{STX_TOP_DIR / 'rules' / 'stmkmf'}'"
+              end
+            end
+            make
+          elsif pkg.name == 'stx:librun'
+            # A workaround for Windows 10 & ancient Borland make which 
+            # tend to crash there when trying to recompile already compiled
+            # librun. Sigh, we have to move away from it as soon as possible!
+            if win32? and (File.exist? "stxmain.c") then
+              touch "stxmain.c"
+            end
+            make
           else
-            make "#{make_vars}"
+            # Somewhat stupid detection whether we run recent St/X or not
+            # ('recent' mean more recent than 3 years or so)
+            # TODO: Remove this hack
+            if File.exist? BUILD_DIR / 'stx' / 'libbasic2' / 'Makefile.init'
+              make "#{make_vars} full"
+            else
+              make "#{make_vars}"
+            end
           end
         end
       end
@@ -285,15 +304,15 @@
     if pkg.application?
       if win32?
         task pkg.name => BUILD_DIR / pkg.directory / 'modules.stx'
-
+        
         task BUILD_DIR / pkg.directory / 'modules.stx' do | t |
           rm t.name if File.exist? t.name
           File.open(t.name, 'w') do | f |
-            project.packages.each do | p |
-              if not p.application? and p.link and not p.test_package? and File.exist? BUILD_DIR / p.directory / OBJ_DIR / p.dll_name()
-                f.puts p.dll_name_without_suffix()
+            project.packages.each do | p |              
+              if not p.application? and p.link and not p.test_package? and p.name != 'stx:stc' and p.name != 'stx:librun' and File.exist? BUILD_DIR / p.directory / OBJ_DIR / p.dll_name()          		
+                f.puts p.dll_name_without_suffix()               
               end
-            end
+            end            
           end
         end
 
--- a/rakelib/support.rb	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/support.rb	Sat Dec 31 22:47:53 2016 +0000
@@ -41,10 +41,8 @@
 # stc and librun repository so the build will fail. 
 def core_developer?
   # JV's box: jv@..., vranyj1@...
-  if (ENV['USER'] == 'jv') or (ENV['USER'] == 'vranyj1')
-    return true
-  end
-  if (ENV['USERNAME'] == 'jv') or (ENV['USERNAME'] == 'vranyj1')
+  user = ENV['USER'] || ENV['USERNAME']
+  if (user == 'jv') or (user == 'vranyj1')
     return true
   end
   return false
--- a/rakelib/workflow.rake	Tue Dec 06 21:32:24 2016 +0000
+++ b/rakelib/workflow.rake	Sat Dec 31 22:47:53 2016 +0000
@@ -11,18 +11,45 @@
         repo = Rake::Stx::Configuration::Repository::find(pkg.repository)
         if repo.type == :'hg' then
           hg = HG::Repository.new(BUILD_DIR / pkg.directory)          
-          yield hg          
+          yield pkg, hg          
         end
       end
     end    
   end
   
   def push(remote, user, pass, review_only, push_bookmark)  
-    hg_repositories do | hg |
+    hg_repositories do | pkg, hg |
       opts = {
         :user => user,
         :pass => pass,
-      }                  
+      }   
+      paths = hg.paths
+      if remote == 'upstream' 
+        if not paths['upstream'] then
+          remote = 'canonical'
+        end
+      elsif remote == 'staging'
+        if not paths['staging'] then
+          puts ""
+          puts "!! repository #{hg.path} has not staging repository defined - skipping !!"
+          puts ""  
+          return
+        end
+      end
+
+      # STC and librun are special - never push them automatically
+      # to upstream / canonical repo, must be done manually. This is 
+      # mainly beacuse there are on separate protected repositories 
+      # not accessible without a special setup. Sigh...
+      if (remote == 'upstream') or (remote == 'canonical') then
+        if (pkg.name == 'stx:stc') or (pkg.name == 'stx:librun') then
+          puts ""
+          puts "== Skipping push of #{pkg.name} - you must push manually =="
+          puts ""          
+          return
+        end
+      end      
+      
       if review_only then
         opts[:rev] = '.'
         remote_url = hg.paths[remote] || remote
@@ -81,7 +108,7 @@
       error "Cannot find 'hg-automerge.rb' in PATH"
     end    
     hg_repositories_failed_to_merge = []
-    hg_repositories do | hg |
+    hg_repositories do | pkg, hg |
       if File.exist? (hg.path / '.hgautomerge') then
         info "Merging #{hg.path}"
         sh "hg-automerge.rb --cwd #{hg.path}"
--- a/specs/baseline.rbspec	Tue Dec 06 21:32:24 2016 +0000
+++ b/specs/baseline.rbspec	Sat Dec 31 22:47:53 2016 +0000
@@ -1,6 +1,8 @@
 project :'stx:baseline' do
 
   repository :'exept:public'
+  package "stx:stc"
+  package "stx:librun"
   package "stx:libbasic"
   package "stx:goodies/refactoryBrowser/helpers"
   package "stx:goodies/refactoryBrowser/parser"
@@ -36,8 +38,6 @@
     task :'checkout:buildtools' => [ BUILD_DIR / 'stx' / "rules",
 				     BUILD_DIR / 'stx' / "configurations",
 				     BUILD_DIR / 'stx' / "support",
-				     BUILD_DIR / 'stx' / "stc",
-				     BUILD_DIR / 'stx' / "librun",
 				     BUILD_DIR / 'stx' / "RELEASE",
 				     # needed by applications for *.rc stuff
                                      BUILD_DIR / 'stx' / 'projects' / 'smalltalk',
@@ -96,18 +96,7 @@
       # the clear is here to avoid multiple checkouts
       t.clear()
     end
-
-    file BUILD_DIR / 'stx' / 'stc' => BUILD_DIR do | t |
-      checkout :'swing:private', 'stx/stc'
-      # the clear is here to avoid multiple checkouts
-      t.clear()
-    end
-
-    file BUILD_DIR / 'stx' / 'librun' => BUILD_DIR do | t |
-      checkout :'swing:private', 'stx/librun'
-      # the clear is here to avoid multiple checkouts
-      t.clear()
-    end
+    
 
     file BUILD_DIR / 'stx' / 'projects' / 'smalltalk' do | t |
       app = project.application
--- a/specs/reports-libjava.rbspec	Tue Dec 06 21:32:24 2016 +0000
+++ b/specs/reports-libjava.rbspec	Sat Dec 31 22:47:53 2016 +0000
@@ -1,43 +1,5 @@
 project :'stx:libjava:reports-common' do
   import :'stx:jv-branch:for-reports-only'
-
-  tasks do
-
-    redefine BUILD_DIR / 'stx' / 'librun' => BUILD_DIR do | t |
-      checkout :'swing:private', 'stx/librun', :branch => 'branches/jv'
-    end
-
-
-    task :'test:pre' => [ BUILD_DIR / 'stx' / 'libjava' / 'tests' ,  ] do
-        chdir BUILD_DIR / 'stx' / 'libjava' / 'libs' / 'java' do
-      if win32? then
-         cmd = 'ant.bat'
-        else
-         cmd = 'ant'
-        end
-          if not system cmd
-            raise "Cannot run maven"
-          end
-        end
-    end
-
-    task :'install:jv:post' do
-      bld_dir = BUILD_DIR / 'stx' / 'libjava'
-      pkg_dir = $install_jv_dirs[:pkg_dir] / 'stx' / 'libjava'
-
-      cp_rx bld_dir / 'examples' ,  pkg_dir / 'examples' do | fname |
-        # fname is full path!!!
-        /\.svn|CVS|\.cvsignore|tests/.match(fname) == nil
-      end
-
-      mkdir pkg_dir / 'java'
-      cp_rx bld_dir / 'java' / 'libs' ,  pkg_dir /  'java' / 'libs' do | fname |
-        # fname is full path!!!
-        /\.svn|CVS|\.cvsignore|tests/.match(fname) == nil
-      end
-
-    end
-  end
 end
 
 project :'stx:libjava:reports' do
--- a/specs/repositories.rbspec	Tue Dec 06 21:32:24 2016 +0000
+++ b/specs/repositories.rbspec	Sat Dec 31 22:47:53 2016 +0000
@@ -22,8 +22,6 @@
 #    and repositories hosted at SWING as upstream repos. 
 #    
 #
-REPOSITORYSET = (ENV['REPOSITORYSET'] || 'default') if not defined? REPOSITORYSET
-
 case REPOSITORYSET 
 when 'default'
   repository :'exept:public' do
--- a/specs/stx-jv.rbspec	Tue Dec 06 21:32:24 2016 +0000
+++ b/specs/stx-jv.rbspec	Sat Dec 31 22:47:53 2016 +0000
@@ -1,3 +1,6 @@
+def build_platform_id() 
+  return "#{ARCH}-#{win32? ? 'win32' : RbConfig::CONFIG['host_os']}"
+end
 # A helper function to download and unpack pre-built stc and librun
 # for those who are not lucky enough to have an access to sources
 def download_blob_matching(pattern, directory)
@@ -11,9 +14,10 @@
   else        
     error_unsupported_platform()
   end
-  build = Jenkins::Build.new(%Q{https://swing.fit.cvut.cz/jenkins/job/stx_jv/ARCH=#{ARCH},PLATFORM=#{plat}N/lastSuccessfulBuild})
-  build.artifacts.each do | artifact |
-    if pattern =~ artifact.name then
+  build = Jenkins::Build.new(%Q{https://swing.fit.cvut.cz/jenkins/job/stx_jv/lastSuccessfulBuild})
+  platform = build_platform_id()
+  build.artifacts.each do | artifact |    
+    if (pattern =~ artifact.name) and (artifact.name.include? platform) then
       if artifact.name.end_with? '.sha256' then
         sha256 = artifact
       else
@@ -42,6 +46,41 @@
   # applications that needs some JV-branch features.
   import :'stx:baseline'
 
+  # FORKED STC and librun
+  package "stx:stc", :repository => :'swing:private:hg', :branch => 'jv', revision: 'feature-block-in-context',
+    :checkout => (Proc.new do | pkg |
+    # Download pre-compiled binary if user has no access to source code    
+    if Rake::Stx::Configuration::Repository::find(pkg.repository) then
+          checkout pkg.repository, 'stx/stc', :branch => pkg.branch, :revision => pkg.revision
+    else
+        download_blob_matching(/prebuilt-stc/, BUILD_DIR / 'stx')
+      end
+    end),
+    :update => (Proc.new do | pkg |
+      if (File.exists? BUILD_DIR / 'stx' / 'stc' / '.hg' / 'hgrc') then
+        update pkg.repository, 'stx/stc', :branch => pkg.branch, :revision => pkg.revision
+      else
+        warn "Not updating #{pkg.name} as no HG repository found in #{BUILD_DIR / 'stx' / 'stc'}"
+    end
+  end)
+
+  package "stx:librun", :repository => :'swing:private:hg', :branch => 'jv', revision: 'feature-block-in-context',
+    :checkout => (Proc.new do | pkg |
+    # Download pre-compiled binary if user has no access to source code
+    if Rake::Stx::Configuration::Repository::find(pkg.repository) then
+          checkout pkg.repository, 'stx/librun', :branch => pkg.branch, :revision => pkg.revision
+    else
+        download_blob_matching(/prebuilt-librun/, BUILD_DIR / 'stx')
+      end
+    end),
+    :update => (Proc.new do | pkg |
+      if (File.exists? BUILD_DIR / 'stx' / 'librun' / '.hg' / 'hgrc') then
+        update pkg.repository, 'stx/stc', :branch => pkg.branch, :revision => pkg.revision
+      else
+        warn "Not updating #{pkg.name} as no HG repository found in #{BUILD_DIR / 'stx' / 'librun'}"
+    end
+  end)
+
   # FORKED libraries
   # ======================================================================
   package "stx:libbasic", :repository => :'bitbucket:janvrany', :branch => 'jv'
@@ -82,22 +121,6 @@
       end
     end
 
-    redefine BUILD_DIR / 'stx' / 'stc' => BUILD_DIR do
-      if Rake::Stx::Configuration::Repository::find(:'swing:private:hg') then
-        checkout :'swing:private:hg', 'stx/stc', :branch => 'jv', :revision => 'feature-block-in-context'
-      else
-        download_blob_matching(/prebuilt-stc/, BUILD_DIR / 'stx')
-      end
-    end
-
-    redefine BUILD_DIR / 'stx' / 'librun' => BUILD_DIR do      
-      if Rake::Stx::Configuration::Repository::find(:'swing:private:hg') then
-        checkout :'swing:private:hg', 'stx/librun', :branch => 'jv', :revision => 'feature-block-in-context'
-      else        
-        download_blob_matching(/prebuilt-librun/, BUILD_DIR / 'stx')
-      end
-    end
-
     # Try execute run the VM if it starts up
     task :'compile:post' do
       if PROJECT == 'stx:jv-branch' then  
@@ -114,57 +137,40 @@
       end
     end
         
-  if win32_wine?
-
-    task :'stx:projects/smalltalk:pre' do   
-      chdir (BUILD_DIR / 'stx' / 'projects' / 'smalltalk') do   
-        make "buildDate.h"    
-      end
-    end
-
-    task :'stx:goodies/xmlsuite/xmlreaderimpl:pre' do
-      chdir (BUILD_DIR / 'stx' / 'goodies' / 'xmlsuite' / 'xmlreaderimpl') do
-        [
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'xmlwf',
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'libexpat',
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'libexpatw',
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'libexpat_static',
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'libexpatw_static',
-          'support' / 'expat-2.0.1' / 'bcb5' / 'release' /'obj' / 'examples'
-        ].each do | f |
-          if not File.exists?(f)
-            mkdir_p f
-          end
+    if win32_wine?
+      task :'stx:projects/smalltalk:pre' do   
+        chdir (BUILD_DIR / 'stx' / 'projects' / 'smalltalk') do   
+          make "buildDate.h"    
         end
       end
-    end
+
     end
 
     # Hack for badly-named files in libtool
     task :'stx:libtool:post' do
       chdir (BUILD_DIR / 'stx' / 'libtool') do
-  # Windows does not support symlinks, copy the file
-  if win32?
-    if not File.exist? 'Tools_BrowserList.STH'
-      cp 'Tools__BrowserList.STH', 'Tools_BrowserList.STH'
-    end
-    if not File.exist? 'Tools_NavigatorModel.STH'
-      cp 'Tools__NavigatorModel.STH', 'Tools_NavigatorModel.STH'
-    end
-    if not File.exist? 'Tools_NavigationState.STH'
-      cp 'Tools__NavigationState.STH', 'Tools_NavigationState.STH'
-    end
-  else
-    if not File.exist? 'Tools_BrowserList.H'
-      ln_s 'Tools__BrowserList.H', 'Tools_BrowserList.H'
-    end
-    if not File.exist? 'Tools_NavigatorModel.H'
-      ln_s 'Tools__NavigatorModel.H', 'Tools_NavigatorModel.H'
-    end
-    if not File.exist? 'Tools_NavigationState.H'
-      ln_s 'Tools__NavigationState.H', 'Tools_NavigationState.H'
-    end
-  end
+        # Windows does not support symlinks, copy the file
+        if win32?
+          if not File.exist? 'Tools_BrowserList.STH'
+            cp 'Tools__BrowserList.STH', 'Tools_BrowserList.STH'
+          end
+          if not File.exist? 'Tools_NavigatorModel.STH'
+            cp 'Tools__NavigatorModel.STH', 'Tools_NavigatorModel.STH'
+          end
+          if not File.exist? 'Tools_NavigationState.STH'
+            cp 'Tools__NavigationState.STH', 'Tools_NavigationState.STH'
+          end
+        else
+          if not File.exist? 'Tools_BrowserList.H'
+            ln_s 'Tools__BrowserList.H', 'Tools_BrowserList.H'
+          end
+          if not File.exist? 'Tools_NavigatorModel.H'
+            ln_s 'Tools__NavigatorModel.H', 'Tools_NavigatorModel.H'
+          end
+          if not File.exist? 'Tools_NavigationState.H'
+            ln_s 'Tools__NavigationState.H', 'Tools_NavigationState.H'
+          end
+        end
       end
     end
   end
@@ -211,27 +217,17 @@
   package "stx:goodies/xmlsuite", :repository => :'bitbucket:janvrany'  
   package "stx:goodies/loggia", :repository => :'exept:public', :link => false
   package 'stx:goodies/smaCC',:repository => :'bitbucket:janvrany'
-  package 'stx:goodies/regression',:repository => :'bitbucket:janvrany', :branch => 'jv', :revision => 'feature-block-in-context', :link => false
+  package 'stx:goodies/regression',:repository => :'bitbucket:janvrany', :branch => 'jv', :link => false
   package "stx:goodies/builder", :repository => :'bitbucket:janvrany',:branch => 'jv', :link => false
   package "stx:goodies/builder/reports"
 
   # Define a "default" test suite, i.e., a set of tests that are run when
   # user does `rake test`. 
-  # The test suite is defined conditionally only when not running under SWING Jenkins. 
-  # Though this is hacky, I'd like a Jenkins job to build exactly the same 
-  # project as user to make sure they're in sync. However, under Jenkins I don't
-  # want them to run - for running tests we have other jobs which run them under
-  # different configurations. 
-  #
-  # This hack will go as soon as SWING Jenkins will switch to pipeline
-  #
-  if (ENV['USER'] != 'builder') and (ENV['USERNAME'] != 'builder') then
-    package 'stx:libview/tests', :test => true;
-    package 'stx:libjava', :test => true;
-    package 'stx:libjava/tools', :test => true;
-    package 'stx:goodies/regression', :test => true;
-    package 'stx:libscm/mercurial', :test => true;
-  end
+  package 'stx:libview/tests', :test => true;
+  package 'stx:libjava', :test => true;
+  package 'stx:libjava/tools', :test => true;
+  package 'stx:goodies/regression', :test => true;
+  package 'stx:libscm/mercurial', :test => true;
 
   tasks do
     # We need to checkout CharacterEncoderCodeGenerator from stx:goodies
@@ -302,14 +298,14 @@
       else
         # Be paranoid, do cleanup here. Should have been done, but who knows...
         cleanup_stc() 
-    	  zip BUILD_DIR / 'stx' / 'stc' , archive: ARTIFACTS_DIR / "#{project.app_name}-#{project.app_version}_#{ARCH}-#{win32? ? 'win32' : RbConfig::CONFIG['host_os']}_prebuilt-stc"
+    	  zip BUILD_DIR / 'stx' / 'stc' , archive: ARTIFACTS_DIR / "#{project.app_name}-#{project.app_version}_#{build_platform_id()}_prebuilt-stc"
       end
       if core_developer? || (File.exist? BUILD_DIR / 'stx' / 'librun' / '.hg') || (File.exist? BUILD_DIR / 'stx' / 'librun' / 'CVS') then
         puts  "WARNING: NOT CREATING librun archive since directory contains sources!!!"
       else
         # Be paranoid, do cleanup here. Should have been done, but who knows...
         cleanup_librun() 
-    	  zip BUILD_DIR / 'stx' / 'librun' , archive: ARTIFACTS_DIR / "#{project.app_name}-#{project.app_version}_#{ARCH}-#{win32? ? 'win32' : RbConfig::CONFIG['host_os']}_prebuilt-librun"
+    	  zip BUILD_DIR / 'stx' / 'librun' , archive: ARTIFACTS_DIR / "#{project.app_name}-#{project.app_version}_#{build_platform_id()}_prebuilt-librun"
       end
     end
   end
@@ -331,13 +327,21 @@
   ver = (ver.split(".")[0..2]).join(".")
   project.app_version "#{ver}_#{BUILD_ID}"
   # This is really ugly. We need to clean that up...
-  BUILD_NAME.replace "#{project.app_name}-#{project.app_version}_#{ARCH}-#{win32? ? 'win32' : RbConfig::CONFIG['host_os']}"
+  BUILD_NAME.replace "#{project.app_name}-#{project.app_version}_#{build_platform_id()}"
 end
 
 
 project :'stx:jv-branch:for-reports-only' do
   import :'stx:jv-branch'
 
+  # Sigh, if we're about to run tests only, we don't want to
+  # run standard tests so we need to clean test flag. 
+  package 'stx:libview/tests', :test => false;
+  package 'stx:libjava', :test => false;
+  package 'stx:libjava/tools', :test => false;
+  package 'stx:goodies/regression', :test => false;
+  package 'stx:libscm/mercurial', :test => false;
+
   tasks do
     task :'stx:projects/smalltalk:pre' do
       chdir BUILD_DIR / 'stx' / 'projects' / 'smalltalk' do