Allow ordering of profile scripts.
authorIain Patterson <me@iain.cx>
Fri, 14 May 2010 13:09:19 +0000 (14:09 +0100)
committerIain Patterson <me@iain.cx>
Fri, 21 May 2010 16:12:46 +0000 (17:12 +0100)
If "# profile-required: X" appears in a file under .profile.d then
ensure that X (which may be a list) is processed before the script in
question.
Always source OS.bashrc, PATH.bashrc and BECOME.bashrc before everything
else, if they exist.
Use this functionality to ensure that p4.bashrc isn't sourced before
vim.bashrc so that P4EDITOR can be set.

.bash_profile
.profile.d/p4.bashrc

index 39276b9..49ea904 100644 (file)
@@ -10,8 +10,57 @@ if tty -s || [ "${0:0:1}" = "-" -o "$1" = "force" ]; then
   # Turn it off to set case-sensitive matching
   LC_ALL=C
 
-  # Source all scripts.
-  for i in ${PROFILE_HOME:-~}/.profile.d/*.bashrc; do . "$i"; done; unset i
+  # Force these to come before everything else.
+  required="OS.bashrc
+PATH.bashrc
+BECOME.bashrc"
+
+  # Remember PATH so we can mangle it to find tsort and sed.
+  path="$PATH"
+  PATH=/usr/bin:/bin:/usr/ccs/bin
+
+  # Sort all scripts by dependencies.
+  profile_d=${PROFILE_HOME:-~}/.profile.d
+  deps=
+  unsorted=
+  for i in $profile_d/*.bashrc; do
+    dep=$(sed -n 's/^##*[      ]*profile-required:[    ]*//p' "$i")
+    i="${i##$profile_d/}"
+    if [ -n "$dep" ]; then
+      for d in $dep; do
+        deps="$deps
+$d $i"
+      done
+    else
+      unsorted="$unsorted
+$i"
+    fi
+  done
+
+  deps="$deps$unsorted"
+
+  # Avoid odd number of tokens for tsort.
+  n=$(echo "$deps" | wc -w)
+  if [ $((n%2)) = 1 ]; then
+    deps="$deps
+${deps##*
+}"
+  fi
+  deps=$(echo "$deps" | tsort)
+  deps="$required
+$deps"
+
+  # Restore PATH.
+  PATH="$path"
+
+  # Source them all in the right order.
+  sourced=
+  for i in $deps; do
+    [ -e "$profile_d/$i" ] || continue
+    [ "${sourced/ $i /}" = "$sourced" ] || continue
+    . "$profile_d/$i"
+    sourced="$sourced $i "
+  done
 
   # Maybe turn nocaseglob back on.
   [ $nocg = 0 ] && shopt -s nocaseglob
@@ -19,5 +68,9 @@ if tty -s || [ "${0:0:1}" = "-" -o "$1" = "force" ]; then
   # Reset LC_ALL.
   LC_ALL=$lc_all
 
+  unset i d n dep deps profile_d path required unsorted sourced
   unset lc_all nocg
+
+  # Don't inherit failure from the last script.
+  true
 fi
index c44932a..2850951 100644 (file)
@@ -1,3 +1,4 @@
+# profile-required: vim.bashrc
 if [ ! -z "$SUDO_USER" ]; then
   export P4USER=$SUDO_USER
   export P4TICKETS=/tmp/.p4tickets.$SUDO_USER