replaces bespoke/env with more robust "where is this script" functions
authorThomas Walker Lynch <xtujpz@reasoningtechnology.com>
Tue, 29 Oct 2024 12:02:06 +0000 (12:02 +0000)
committerThomas Walker Lynch <xtujpz@reasoningtechnology.com>
Tue, 29 Oct 2024 12:02:06 +0000 (12:02 +0000)
39 files changed:
developer/javac/Mosaic.java
developer/javac/Util.java
developer/scratch_pad/.gitignore [deleted file]
developer/scratchpad/.gitignore [new file with mode: 0644]
developer/shell/Mosaic [deleted file]
developer/tool/#release# [deleted file]
developer/tool/clean_build_directories
developer/tool/clean_javac_output
developer/tool/clean_make_output
developer/tool/clean_release
developer/tool/distribute_source [new file with mode: 0755]
developer/tool/make
developer/tool/release
document/directory_naming.html
document/todo.txt
release/Mosaic.jar
tester/alias/com/ReasoningTechnology/Mosaic/Test [new symlink]
tester/document/emacs_jdb.txt [new file with mode: 0644]
tester/document/what_the_tests_do.txt
tester/javac/Test0.java
tester/javac/TestIO.java [deleted file]
tester/javac/TestMosaic_0.javax
tester/javac/Test_IO.java [new file with mode: 0644]
tester/javac/Test_Util.java [new file with mode: 0644]
tester/jvm/TestBenchMosaic.jar [deleted file]
tester/jvm/Test_Mosaic.jar [new file with mode: 0644]
tester/scratch_pad/.gitignore [deleted file]
tester/scratchpad/.gitignore [new file with mode: 0644]
tester/shell/TestIO [deleted file]
tester/shell/Test_IO [new file with mode: 0755]
tester/shell/Test_Util [new file with mode: 0755]
tester/tool/clean_build_directories
tester/tool/env
tester/tool/make
tester/tool/shell_wrapper_list
tool_shared/bespoke/env
tool_shared/bespoke/env3 [new file with mode: 0644]
tool_shared/bespoke/env_orig [new file with mode: 0644]
tool_shared/bespoke/test_env [new file with mode: 0755]

index adc43c4..d20baae 100644 (file)
@@ -1,4 +1,4 @@
-package com.ReasoningTechnology.Mosaic.Test;
+package com.ReasoningTechnology.Mosaic;
 import com.ReasoningTechnology.Mosaic.Util;
 
 /*
index 9e15eee..45f2a53 100644 (file)
@@ -12,20 +12,19 @@ import java.time.format.DateTimeFormatter;
 
 public class Util{
 
-  // typically used to gather results before a return
+  // Typically used to gather conditions before returning a test result.
+  // As this is used for testing, and an empty conditions list is unusual,
+  // returns false for an empty conditions list.
   public static boolean all(boolean[] conditions){
-    for( boolean condition : conditions ){
-      if( !condition ){
-        return false;
-      }
-    }
+    if( conditions.length == 0 ) return false;
+    for(boolean condition : conditions) if(!condition) return false;
     return true;
   }
   public static void all_set_false(boolean[] conditions){
-    for( boolean condition : conditions ) condition = false;
+    for(boolean condition : conditions) condition = false;
   }
   public static void all_set_true(boolean[] conditions){
-    for( boolean condition : conditions ) condition = true;
+    for(boolean condition : conditions) condition = true;
   }
 
   public static String iso_utc_time(){
diff --git a/developer/scratch_pad/.gitignore b/developer/scratch_pad/.gitignore
deleted file mode 100644 (file)
index 120f485..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!/.gitignore
diff --git a/developer/scratchpad/.gitignore b/developer/scratchpad/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore
diff --git a/developer/shell/Mosaic b/developer/shell/Mosaic
deleted file mode 100755 (executable)
index ba5b241..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-java com.ReasoningTechnology."Mosaic".Mosaic
diff --git a/developer/tool/#release# b/developer/tool/#release#
deleted file mode 100755 (executable)
index 9ca9125..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env bash
-
-# input guards
-
-  if [ -z "$REPO_HOME" ]; then
-    echo "$(script_fp):: REPO_HOME is not set."
-    exit 1
-  fi
-
-  env_must_be="developer/tool/env"
-  if [ "$ENV" != "$env_must_be" ]; then
-    echo "$(script_fp):: error: must be run in the $env_must_be environment"
-    exit 1
-  fi
-
-# script local environment
-
-  release_dir="$REPO_HOME/release"
-  shell_dir="$REPO_HOME/developer/shell"
-  project_jar_fp="$REPO_HOME/developer/jvm/"$PROJECT".jar"
-  wrapper=$(shell_wrapper_list)
-
-
-  if [ ! -d "$release_dir" ]; then
-    mkdir -p "$release_dir"
-  fi
-
-  # Function to copy and set permissions
-  install_file() {
-    source_fp="$1"
-    target_dp="$2"
-    perms="$3"
-
-    target_file="$target_dp/$(basename "$source_fp")"
-
-    if [ ! -f "$source_fp" ]; then
-      echo "install_file:: Source file '$source_fp' does not exist."
-      return 1
-    fi
-
-    if ! install -m "$perms" "$source_fp" "$target_file"; then
-      echo "Error: Failed to install $(basename "$source_fp") to $target_dp"
-      exit 1
-    else
-      echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms"
-    fi
-  }
-# do the release
-
-  echo "Starting release process..."
-
-  # Install the JAR file
-  install_file "$project_jar_fp" "$release_dir" "ug+r"
-
-  # Install shell wrappers
-  for wrapper in $wrapper; do
-    install_file "$shell_dir/$wrapper" "$release_dir" "ug+r+x"
-  done
-
-echo "$(script_fp) done."
index 5165c3a..8990e26 100755 (executable)
@@ -15,7 +15,7 @@
 # remove files
   set -x
   cd "$REPO_HOME"/developer
-  rm -r scratch_pad/*
+  rm -r scratchpad/*
   rm jvm/*
   rm shell/*
   set +x
index 88d8f3d..1f94c43 100755 (executable)
@@ -11,7 +11,7 @@
 # remove files
   set -x
   cd "$REPO_HOME"/developer
-  rm -r scratch_pad/com/ReasoningTechnology/"$PROJECT"
+  rm -r scratchpad/com/ReasoningTechnology/"$PROJECT"
   set +x
 
 echo "$(script_fn) done."
index 2a3acd5..af7c00a 100755 (executable)
@@ -17,7 +17,7 @@
 
   set -x
   cd "$REPO_HOME"/developer
-  rm -r scratch_pad/com/ReasoningTechnology/"$PROJECT"
+  rm -r scratchpad/com/ReasoningTechnology/"$PROJECT"
   rm jvm/"$PROJECT".jar
   rm shell/{$wrapper}
   set +x
index fc31cde..ec10d91 100755 (executable)
@@ -17,7 +17,7 @@
 # remove files
   set -x
   cd "$REPO_HOME"/developer
-  rm -r scratch_pad/com/ReasoningTechnology/"$PROJECT"
+  rm -r scratchpad/com/ReasoningTechnology/"$PROJECT"
   rm jvm/"$PROJECT".jar
   rm shell/{$wrapper}
   rm -f "$release_dir"/"$PROJECT".jar
diff --git a/developer/tool/distribute_source b/developer/tool/distribute_source
new file mode 100755 (executable)
index 0000000..003dd3d
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/env bash
+
+# This script links the sources into the directory tree in parallel to the package.
+
+# Input guards
+
+  env_must_be="developer/tool/env"
+  if [ "$ENV" != "$env_must_be" ]; then
+    echo "$(script_fp):: error: must be run in the $env_must_be environment"
+    exit 1
+  fi
+
+  cd "$REPO_HOME"/developer
+
+# Link sources into the package tree
+
+  package_tree="scratchpad/com/ReasoningTechnology/$PROJECT"
+  mkdir -p "$package_tree"
+  echo "Package: $package_tree"
+
+  echo -n "Linking:"
+  for source_file in javac/*.java; do
+    echo -n " $(basename "$source_file")"
+    link_target="$package_tree/$(basename "$source_file")"
+    if [ ! -L "$link_target" ]; then
+      ln -s "$(realpath --relative-to="$package_tree" "$source_file")" "$link_target"
+    fi
+  done
+  echo "."
+
+echo "$(script_fp) done."
index 92e3ba2..16b477b 100755 (executable)
@@ -12,7 +12,7 @@
 
 echo "Compiling files..."
   set -x
-  javac -d scratch_pad javac/*.java
+  javac -g -d scratchpad javac/*.java
   set +x
   if [ $? -ne 0 ]; then
     echo "Compilation failed."
@@ -23,7 +23,7 @@ echo "Creating JAR file..."
   set -x
   jar_file=jvm/"$PROJECT".jar
   mkdir -p jvm
-  jar cf $jar_file -C scratch_pad .
+  jar cf $jar_file -C scratchpad .
   set +x
   if [ $? -eq 0 ]; then
     echo "JAR file created successfully: $jar_file"
index 8129f15..9ca9125 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # input guards
 
index 64ab608..f5ee0a0 100644 (file)
           <li>document/ <span class="description">Documentation on developing and building the project.</span></li>
           <li>javac/ <span class="description">Java source files for compilation.</span></li>
           <li>jvm/ <span class="description">Compiled Java bytecode files for the project, typically a jar for a Java project.</span></li>
-          <li>scratch_pad/ <span class="description">Temporary storage typically for intermediate files created during build.</span></li>
+          <li>scratchpad/ <span class="description">Temporary storage typically for intermediate files created during build.</span></li>
           <li>shell/ <span class="description">Shell scripts intended to be part of the project release. (These are not tools.)</span></li>
           <li>tool/ <span class="description">Tools created by the developer, used for development tasks.</span></li>
         </ul>
         <li>document/ <span class="description">General documentation about the project.</span></li>
         <li>release/ <span class="description">Release candidate for testing. Becomes the release on the release branch.</span></li>
-        <li>scratch_pad/ <span class="description">Temporary storage for project administration tasks.</span></li>
+        <li>scratchpad/ <span class="description">Temporary storage for project administration tasks.</span></li>
         <li>tester/ <span class="description">Workspace for the tester. Has the test bench, tests, and test scripts.</span></li>
         <ul>
           <li>document/ <span class="description">Test-specific documentation.</span></li>
       
     <p>When attempting to apply the <code>is-for</code> property in practice it
       became apparent that using this sole property was insufficient.  Consider
-      the directories <code>deprecated/</code> and <code>scratch_pad/</code>. There is no
-      <em>Mr. Deprecated</em> or <em>Mr. Scratch_Pad</em> who the contained
+      the directories <code>deprecated/</code> and <code>scratchpad/</code>. There is no
+      <em>Mr. Deprecated</em> or <em>Mr. Scratchpad</em> who the contained
       files are for. (And this conclusion is not for the lack of trying. Even
       mythological beings did not suffice as agents.) Rather than being for an
       agent, the files collected in such a directory have in common a state of
       being that was imposed upon them by decree.  Perhaps the developer, has
       decreed that a file is now deprecated, or a build script has decreed that
-      it is a scratch_pad file. Such decrees are typically more dynamic than the
+      it is a scratchpad file. Such decrees are typically more dynamic than the
       relationship properties. Also, these properties are disconnected from the
       contents of the file.  When, for example, a file has the property of being
       for the java compiler, we gain some information about its contents. In the
index fc554b1..b812708 100644 (file)
@@ -20,3 +20,9 @@ Updates for Ariadne
 
 5. fix many shebangs to be: #!/usr/bin/env bash
 
+6. scratch_pad -> scratchpad
+
+5. make_source_tree also integrated into make
+
+6. replacement for bespoke/env
+
index 878a371..aa4a400 100644 (file)
Binary files a/release/Mosaic.jar and b/release/Mosaic.jar differ
diff --git a/tester/alias/com/ReasoningTechnology/Mosaic/Test b/tester/alias/com/ReasoningTechnology/Mosaic/Test
new file mode 120000 (symlink)
index 0000000..6af8f49
--- /dev/null
@@ -0,0 +1 @@
+/var/user_data/Thomas-developer/Mosaic//tester/javac
\ No newline at end of file
diff --git a/tester/document/emacs_jdb.txt b/tester/document/emacs_jdb.txt
new file mode 100644 (file)
index 0000000..ff124a4
--- /dev/null
@@ -0,0 +1,18 @@
+
+jdb will be in the third_party tools directory:
+
+  2024-10-27T09:34:37Z[Mosaic_tester]
+  Thomas-developer@Blossac§/var/user_data/Thomas-developer/Mosaic/tester§
+  > which jdb
+  /var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11/bin/jdb
+
+If Emacs has been run from outside of `env_developer`  or `env_tester` then
+emacs will not see the path to tool_shared/third_party. Emacs can be told
+explicitly:
+
+  (setenv "PATH" (concat (getenv "PATH") ":/var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11/bin"))
+  (setq exec-path (append exec-path '("/var/user_data/Thomas-developer/Mosaic/tool_shared/third_party/jdk-11/bin")))
+
+but this probably won't work as other things will also be missing from the
+environment.So either run emacs in the correct environment, or run jdb from a
+shell after sourcing the environment.
index 53762c6..85563b6 100644 (file)
@@ -1,6 +1,7 @@
 
-Test the Mosaic test bench
-javac/TestMoasic.java
+Should probably finish this doc ;-)
+
+
 
 
 
index 8746515..40c4ef8 100644 (file)
@@ -1,4 +1,3 @@
-package com.ReasoningTechnology.Mosaic.Test;
 import com.ReasoningTechnology.Mosaic.Util;
 
 /*
diff --git a/tester/javac/TestIO.java b/tester/javac/TestIO.java
deleted file mode 100644 (file)
index 0b0ffbf..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.ReasoningTechnology.Mosaic.Test;
-import com.ReasoningTechnology.Mosaic.IO;
-import com.ReasoningTechnology.Mosaic.Util;
-
-public class TestIO{
-
-  public static int fut(){
-    try{
-      // Echo some characters from stdin to stdout
-      System.out.print((char) System.in.read());
-      System.out.print((char) System.in.read());
-
-      // Echo some more characters from stdin to stderr
-      System.err.print((char) System.in.read());
-      System.err.print((char) System.in.read());
-
-      // Count remaining characters until EOF
-      int count = 0;
-      while(System.in.read() != -1){
-        count++;
-      }
-
-      return count;
-    } catch(Exception e){
-      e.printStackTrace();
-      return -1; // Error case
-    }
-  }
-
-  public static int run(){
-    IO io = new IO();
-    boolean[] condition = new boolean[3];
-
-    // Redirect IO streams
-    io.redirect();
-
-    // Provide input for the function under test
-    io.push_input("abcdefg");
-
-    // Execute function under test
-    int result = fut();
-
-    // Check stdout content
-    String stdout_string = io.get_out_content();
-    condition[0] = stdout_string.equals("ab");
-
-    // Check stderr content
-    String stderr_string = io.get_err_content();
-    condition[1] = stderr_string.equals("cd");
-
-    // Check returned character count (3 remaining characters: 'e','f','g')
-    condition[2] = result == 3;
-
-    // Restore original IO streams
-    io.restore();
-
-    if(!Util.all(condition)){
-      System.out.println("TestIO failed");
-      return 1;
-    }
-    System.out.println("TestIO passed");
-    return 0;
-  }
-
-  // Main function to provide a shell interface for running tests
-  public static void main(String[] args){
-    int return_code = run();
-    System.exit(return_code); 
-    return;
-  }
-
-}
-
-
index 38307cc..8e1a782 100644 (file)
@@ -1,5 +1,3 @@
-package com.ReasoningTechnology.Mosaic.Test;
-
 /*
 Component smoke test. At least call each method of each class.
 
diff --git a/tester/javac/Test_IO.java b/tester/javac/Test_IO.java
new file mode 100644 (file)
index 0000000..d6621fe
--- /dev/null
@@ -0,0 +1,73 @@
+import com.ReasoningTechnology.Mosaic.IO;
+import com.ReasoningTechnology.Mosaic.Util;
+
+public class Test_IO{
+
+  public static int fut(){
+    try{
+      // Echo some characters from stdin to stdout
+      System.out.print((char) System.in.read());
+      System.out.print((char) System.in.read());
+
+      // Echo some more characters from stdin to stderr
+      System.err.print((char) System.in.read());
+      System.err.print((char) System.in.read());
+
+      // Count remaining characters until EOF
+      int count = 0;
+      while(System.in.read() != -1){
+        count++;
+      }
+
+      return count;
+    } catch(Exception e){
+      e.printStackTrace();
+      return -1; // Error case
+    }
+  }
+
+  public static int run(){
+    IO io = new IO();
+    boolean[] condition = new boolean[3];
+
+    // Redirect IO streams
+    io.redirect();
+
+    // Provide input for the function under test
+    io.push_input("abcdefg");
+
+    // Execute function under test
+    int result = fut();
+
+    // Check stdout content
+    String stdout_string = io.get_out_content();
+    condition[0] = stdout_string.equals("ab");
+
+    // Check stderr content
+    String stderr_string = io.get_err_content();
+    condition[1] = stderr_string.equals("cd");
+
+    // Check returned character count (3 remaining characters: 'e','f','g')
+    condition[2] = result == 3;
+
+    // Restore original IO streams
+    io.restore();
+
+    if(!Util.all(condition)){
+      System.out.println("Test_IO failed");
+      return 1;
+    }
+    System.out.println("Test_IO passed");
+    return 0;
+  }
+
+  // Main function to provide a shell interface for running tests
+  public static void main(String[] args){
+    int return_code = run();
+    System.exit(return_code); 
+    return;
+  }
+
+}
+
+
diff --git a/tester/javac/Test_Util.java b/tester/javac/Test_Util.java
new file mode 100644 (file)
index 0000000..0d0edba
--- /dev/null
@@ -0,0 +1,78 @@
+import com.ReasoningTechnology.Mosaic.Util;
+
+/*
+Test_Util
+
+*/
+
+public class Test_Util{
+
+  public static boolean test_all(){
+    // Test with zero conditions
+    boolean[] conditions0 = {};
+    boolean result = !Util.all(conditions0);  // Empty conditions list is false.
+
+    // Test with one condition
+    boolean[] conditions1_true = {true};
+    boolean[] conditions1_false = {false};
+    result &= Util.all(conditions1_true);    // should return true
+    result &= !Util.all(conditions1_false);  // should return false
+
+    // Test with two conditions
+    boolean[] conditions2_true = {true, true};
+    boolean[] conditions2_false1 = {true, false};
+    boolean[] conditions2_false2 = {false, true};
+    boolean[] conditions2_false3 = {false, false};
+    result &= Util.all(conditions2_true);     // should return true
+    result &= !Util.all(conditions2_false1);  // should return false
+    result &= !Util.all(conditions2_false2);  // should return false
+    result &= !Util.all(conditions2_false3);  // should return false
+
+    // Test with three conditions
+    boolean[] conditions3_false1 = {true, true, false};
+    boolean[] conditions3_true = {true, true, true};
+    boolean[] conditions3_false2 = {true, false, true};
+    boolean[] conditions3_false3 = {false, true, true};
+    boolean[] conditions3_false4 = {false, false, false};
+    result &= !Util.all(conditions3_false1); // should return false
+    result &= Util.all(conditions3_true);    // should return true
+    result &= !Util.all(conditions3_false2); // should return false
+    result &= !Util.all(conditions3_false3); // should return false
+    result &= !Util.all(conditions3_false4); // should return false
+
+    return result;
+  }
+
+  public static boolean test_all_set_false(){
+    boolean[] conditions = {true, true, true};
+    Util.all_set_false(conditions);
+    return !Util.all(conditions);  // Should return false after setting all to false
+  }
+
+  public static boolean test_all_set_true(){
+    boolean[] conditions = {false, false, false};
+    Util.all_set_true(conditions);
+    return Util.all(conditions);  // Should return true after setting all to true
+  }
+  
+  public static int run(){
+    boolean[] condition = new boolean[3];
+    condition[0] = test_all();
+    condition[1] = test_all_set_false();
+    condition[2] = test_all_set_true();
+
+    if( !Util.all(condition) ){
+      System.out.println("Test_Util failed");
+      return 1;
+    }
+    System.out.println("Test_Util passed");
+    return 0;
+  }
+
+  // Main function to provide a shell interface for running tests
+  public static void main(String[] args){
+    int return_code = run();
+    System.exit(return_code); 
+    return;
+  }
+}
diff --git a/tester/jvm/TestBenchMosaic.jar b/tester/jvm/TestBenchMosaic.jar
deleted file mode 100644 (file)
index 17ab80c..0000000
Binary files a/tester/jvm/TestBenchMosaic.jar and /dev/null differ
diff --git a/tester/jvm/Test_Mosaic.jar b/tester/jvm/Test_Mosaic.jar
new file mode 100644 (file)
index 0000000..05330e3
Binary files /dev/null and b/tester/jvm/Test_Mosaic.jar differ
diff --git a/tester/scratch_pad/.gitignore b/tester/scratch_pad/.gitignore
deleted file mode 100644 (file)
index 120f485..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!/.gitignore
diff --git a/tester/scratchpad/.gitignore b/tester/scratchpad/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore
diff --git a/tester/shell/TestIO b/tester/shell/TestIO
deleted file mode 100755 (executable)
index 670538a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/env bash
-java com.ReasoningTechnology.Mosaic.Test.TestIO
diff --git a/tester/shell/Test_IO b/tester/shell/Test_IO
new file mode 100755 (executable)
index 0000000..1de1b73
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/env bash
+java com.ReasoningTechnology.Mosaic.Test.Test_IO
diff --git a/tester/shell/Test_Util b/tester/shell/Test_Util
new file mode 100755 (executable)
index 0000000..a95a289
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/env bash
+java com.ReasoningTechnology.Mosaic.Test.Test_Util
index a3480cb..3338096 100755 (executable)
@@ -15,7 +15,7 @@
 # remove files
   set -x
   cd "$REPO_HOME"/tester
-  rm -r scratch_pad/*
+  rm -r scratchpad/*
   rm jvm/*
   rm shell/*
   set +x
index bd42c24..a31f599 100644 (file)
@@ -24,8 +24,7 @@ export PATH=\
 export CLASSPATH=\
 "$JAVA_HOME"/lib\
 :"$REPO_HOME"/release/"$PROJECT".jar\
-:"$REPO_HOME"/tester/jvm/TestBench.jar\
-:"$REPO_HOME"/tester/jvm/TestBench"$PROJECT".jar\
+:"$REPO_HOME"/tester/jvm/Test_"$PROJECT".jar\
 :"$CLASSPATH"
 
 # misc
index 2c99c27..717240a 100755 (executable)
@@ -12,8 +12,8 @@ echo "Compiling files..."
 
   set -x
   cd $REPO_HOME/tester
-  javac -d scratch_pad javac/*.java
-  jar cf jvm/TestBench"$PROJECT".jar -C scratch_pad .
+  javac -g -d scratchpad javac/*.java
+  jar cf jvm/Test_"$PROJECT".jar -C scratchpad .
   set +x 
 
 echo "Creating shell wrappers..."
index 9d481fe..55229fe 100755 (executable)
@@ -8,5 +8,5 @@ if [ "$ENV" != "$env_must_be" ]; then
 fi
 
 # space separated list of shell interface wrappers
-echo Test0 TestIO
+echo Test0 Test_Util Test_IO 
  
index f36023e..80c44fb 100644 (file)
@@ -1,57 +1,80 @@
 #!/usr/bin/env bash
-# environment shared by entire project
-# number one task, establish REPO_HOME
-# this is specific to this script being in the .../tools_shared/env directory
 
-  export PROJECT=$(basename "$REPO_HOME")
-
-  ## set the shell prompt to show the project
-  PPS1="\n[$PROJECT]\n\u@\h§$(pwd)§\n> "
-  PPS2=">> "
-
-# some useful functions for environment scripts
-
-  ## path to script file
-  script_fp() {
-    eval "
-      local script_dp=\$(dirname \$(realpath \${BASH_SOURCE[1]}))
-      echo \$(realpath --relative-to=\"$REPO_HOME\" \"\$script_dp\")/\$(script_fn)
-    "
+# This is the base environment shared by all roles in the project.
+
+# The project administrator sets up the following tools for all roles to use:
+#
+  export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+
+# Absolute path to script file. The use of eval makes it suitable for exporting
+# and use with other scripts
+
+       read -r -d '' script_afp_string <<-"EOF"
+         # get the top of the BASH_SOURCE stack
+         local top_index=$(( ${#BASH_SOURCE[@]} - 1 ))
+         local bash_source="${BASH_SOURCE[$top_index]}"
+       
+         # echo
+         # for (( i=0; i<=top_index; i++ )); do
+         #   echo "$i: ${BASH_SOURCE[$i]}"
+         # done
+         # echo "bash_source (top of stack): $bash_source"
+       
+         # Resolve the absolute file path
+         local afp
+         afp=$(realpath "$bash_source" 2>/dev/null)
+         if [[ $? -ne 0 ]]; then
+           echo 'Error: Failed to resolve path in script_afp.' >&2
+           return 1
+         fi
+         echo "$afp"
+       EOF
+       
+  script_afp(){
+    eval "$script_afp_string"
   }
 
-  ## path to script directory
-  script_dp() {
-    eval "
-      local script_dp=\$(dirname \$(realpath \${BASH_SOURCE[1]}))
-      echo \$(realpath --relative-to=\"$REPO_HOME\" \"\$script_dp\")
-    "
+  script_adp(){
+    dirname "$(script_afp)"
   }
 
-  ## an env script will be in workspace/tool/env, so
-  workspace(){
-    eval "echo \$(dirname \$(script_dp))"
-  }
 
-  ## script's filename
-  script_fn() {
-    eval "echo \$(basename \${BASH_SOURCE[1]})"
-  }
+# This script assumes it is located at $REPO_HOME/tools_shared/bespoke and works
+# backwards to recover $REPO_HOME, etc.
 
-  export -f script_fp script_dp script_fn workspace
+  REPO_HOME=$(dirname "$(dirname "$(script_adp)")")
+  echo REPO_HOME "$REPO_HOME"
 
-# note to the programs which environment they are running.
+  PROJECT=$(basename "$REPO_HOME")
+  echo PROJECT "$PROJECT"
+  PROMPT_DECOR=$PROJECT
 
-  export ENV=$(script_fp)
 
-# The project administrator setup these tools and environment settings for all
-# on the project to use:
+# These functions are offered as a convenience to be run inside other scripts.
+# These produce $REPO_HOME relative results, and thus preferred over script_adp.
 
-export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+  ## script's filename
+  script_fn(){
+    basename "$(script_afp)"
+  }
+
+  ## script's dirpath relative to $REPO_HOME
+  script_fp(){
+    realpath --relative-to="${REPO_HOME}" "$(script_afp)"
+  }
 
-# some feedback to show all went well
+  ## script's dirpath relative to $REPO_HOME
+  script_dp(){
+    dirname "$(script_fp)"
+  }
 
-echo ENV "$ENV"
-echo PROJECT "$PROJECT"
+# Exports, and give the exported environment a name
+# Bash has no 'closure' hence when exporting a function, one must also export all the pieces.
 
+  export REPO_HOME PROJECT PROMPT_DECOR
+  export script_afp_string
+  export -f script_afp script_adp script_fn script_dp script_fp
 
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
 
diff --git a/tool_shared/bespoke/env3 b/tool_shared/bespoke/env3
new file mode 100644 (file)
index 0000000..9fb26ef
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/bash
+
+# This is the base environment shared by all roles in the project.
+
+# The project administrator sets up the following tools for all roles to use:
+#
+export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+
+# Absolute path to script directory, for local use in other functions, but the use
+# of eval makes it suitable for exporting and use with other scripts if that
+# is found to be useful. However note the functions that return project relative
+# paths further below.
+
+read -r -d '' script_adp_string <<-"EOF"
+  local bash_source
+  if [[ -n "${BASH_SOURCE[1]}" ]]; then
+    bash_source="${BASH_SOURCE[1]}"
+  elif [[ -n "${BASH_SOURCE[0]}" ]]; then
+    bash_source="${BASH_SOURCE[0]}"
+  else
+    echo 'Error: Unable to determine script path in script_adp.' >&2
+    return 1
+  fi
+  #echo
+  #echo bash_source: $bash_source
+  local absolute_script_dp
+  absolute_script_dp=$(dirname "$(realpath "$bash_source" 2>/dev/null)")
+  if [[ $? -ne 0 ]]; then
+    echo 'Error: Failed to resolve path in script_adp.' >&2
+    return 1
+  fi
+  echo "$absolute_script_dp"
+EOF
+script_adp(){
+  eval "$script_adp_string"
+}
+
+
+
+# Exports, and give the exported environment a name
+#
+
+  export script_adp_string 
+  export -f script_adp
+#  export -f script_adp script_fn script_dp script_fp workspace
+#  export ENV=$(script_fp)
+#  echo ENV "$ENV"
+  
diff --git a/tool_shared/bespoke/env_orig b/tool_shared/bespoke/env_orig
new file mode 100644 (file)
index 0000000..04daca8
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/bash
+
+# This is the base environment shared by all roles in the project.
+
+# The project administrator sets up the following tools for all roles to use:
+#
+export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
+
+# Absolute path to script directory, the use of eval makes it suitable for
+# exporting and use with other scripts
+
+read -r -d '' script_adp_string <<-"EOF"
+  local bash_source
+  if [[ -n "${BASH_SOURCE[1]}" ]]; then
+    bash_source="${BASH_SOURCE[1]}"
+  elif [[ -n "${BASH_SOURCE[0]}" ]]; then
+    bash_source="${BASH_SOURCE[0]}"
+  else
+    echo 'Error: Unable to determine script path in script_adp.' >&2
+    return 1
+  fi
+  echo
+  echo 0: ${BASH_SOURCE[0]}
+  echo 1: ${BASH_SOURCE[1]}
+  echo bash_source: $bash_source
+  local adp
+  adp=$(dirname "$(realpath "$bash_source" 2>/dev/null)")
+  if [[ $? -ne 0 ]]; then
+    echo 'Error: Failed to resolve path in script_adp.' >&2
+    return 1
+  fi
+  echo "$adp"
+EOF
+  script_adp(){
+    eval "$script_adp_string"
+  }
+
+
+# This script assumes it is located at $REPO_HOME/tools_shared/bespoke and works
+# backwards to recover $REPO_HOME, etc.
+
+  REPO_HOME=$(dirname "$(dirname "$(script_adp)")")
+  echo REPO_HOME "$REPO_HOME"
+
+  PROJECT=$(basename "$REPO_HOME")
+  echo PROJECT "$PROJECT"
+  PROMPT_DECOR=$PROJECT
+
+
+# These functions are offered as a convenience to be run inside other scripts.
+# These produce $REPO_HOME relative results, and thus preferred over script_adp.
+
+  ## script's filename
+read -r -d '' script_fn_string <<-"EOF" 
+  local source_file="${BASH_SOURCE[1]:-${BASH_SOURCE[0]}}"
+  if [[ -z "$source_file" ]]; then
+    echo 'Error: Unable to determine script filename in script_fn.' >&2
+    return 1
+  fi
+  echo $(basename "$source_file")
+EOF
+  script_fn(){
+    eval "$script_fn_string"
+  }
+
+
+  ## path to script directory relative to $REPO_HOME
+read -r -d '' script_dp_string <<-"EOF" 
+  local rh="${REPO_HOME}"
+  echo
+  echo "REPO_HOME: ${rh}"
+
+  local adp
+  adp=$(script_adp)
+  echo "adp: ${adp}"
+
+  if [[ -z "${adp}" ]]; then
+    echo 'Error: script_adp returned an empty path in script_dp.' >&2
+    return 1
+  fi
+
+  realpath --relative-to="${rh}" "${adp}" || echo 'Error resolving path in script_dp' >&2
+EOF
+  script_dp(){
+    eval "$script_dp_string"
+    echo dp
+  }
+
+   ## script's filepath relative to $REPO_HOME
+read -r -d '' script_fp_string <<-"EOF" 
+  local dp fn
+  dp=$(script_dp)
+  fn=$(script_fn)
+  if [[ -z "$dp" || -z "$fn" ]]; then
+    echo 'Error: script_fp encountered an empty path component.' >&2
+    return 1
+  fi
+  echo "$dp/$fn"
+EOF
+  script_fp(){
+    eval "$script_fp_string"
+  }
+
+  ## this script assumes it is located in workspace/tool/env, so
+  workspace(){
+    eval "echo \$(dirname \$(script_dp))"
+  }
+
+# Exports, and give the exported environment a name
+# Bash has no 'closure' hence when exporting a function, one must also export all the pieces.
+
+  export REPO_HOME PROJECT PROMPT_DECOR PPS1 PPS2 
+  export script_adp_string script_fn_string script_dp_string script_fp_string
+  export -f script_adp script_fn script_dp script_fp workspace
+
+  export ENV=$(script_fp)
+  echo ENV "$ENV"
+
diff --git a/tool_shared/bespoke/test_env b/tool_shared/bespoke/test_env
new file mode 100755 (executable)
index 0000000..59546a1
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/env bash
+# try both running and sourcing this test
+
+echo "REPO_HOME:" "$REPO_HOME"
+echo "PROJECT:" "$PROJECT"
+
+echo "script_afp:" "$(script_afp)"
+echo "script_adp:" "$(script_adp)"
+echo "script_fn:" "$(script_fn)"
+echo "script_fp:" "$(script_fp)"
+echo "script_dp:" "$(script_dp)"
+echo "ENV:" "$ENV"