Previous: , Up: Build Scripts   [Index]


B.4 Update RC Files

This code synchronizes the following configuration files:

It first verifies that the files differ; then it will copy a newer file over an older file. If a local file is updated with a newer template file, then this program updates the Emacs server-socket-dir variable, if such exists. If a template is updated with a newer local file, then delete the server-socket-dir value.

[ -v TEMPLATES ] || {
    printf "${RED}ERROR: missing \$TEMPLATES env var${CLEAR}\n"
    exit 1
}

[ -v COMP ] || {
    printf "${RED}ERROR: missing \$COMP env var${CLEAR}\n"
    exit 1
}

set -e

## usage: syncrc [-f system|rc -t rc|system -h]
## if no options, process by natural age
## if -f and -t options, force update from ... to ...
usage () {
      printf "\n${GREEN}USAGE: ${YELLOW}syncrc \
${WHITEBOLD}[${CYAN}-f ${MAGENTA}system|rc \
${CYAN}-t ${MAGENTA}rc|system \
${WHITEBOLD}]${CLEAR}\n"

      printf "${GREEN}force sync rc files \
${CYAN}'-f'${GREEN}rom ${MAGENTA}system|rc \
${CYAN}'-t'${GREEN}o ${MAGENTA}rc|system\
${CLEAR}\n\n"
      exit $1
}

# force update of either system or rc file
touchup () {
  printf "In touchup with \$from: $from\n";
      case $from in
          "system") printf "${WHITEBOLD}Touching $1..."; sudo touch $1; printf "${CLEAR}" ;;
          "rc")     printf "${WHITEBOLD}Touching $2..."; touch $2; printf "${CLEAR}" ;;
      esac
}

# compare files to determine which one is newer
comp () {
      [[ -e $1 && -e $2 ]] && { # only process if both files exist
      if ! cmp -s $1 $2
      then
          [[ -n $from ]] && { # force update if $from is non-zero length
              touchup $1 $2
          } || { :; }
          [[ $1 -nt $2 ]] && { # system file is newer
              [[ -d $(dirname "$2") ]] || { # make sure rc dir exists
                  mkdir -vp $(dirname "$2")
              } || { :; }

              printf "${YELLOW}system is newer than rc${CLEAR}\n"
              echo; ls -l $1 $2; echo
                        printf "${BLUE}";
                        cp -ipv "$1" "$2";
                        printf "${CLEAR}"

                        ## delete the value of the emacs server-socket-dir in the rc file
                        grep -q "EMACS_SERVER_SOCKET_DIR=" "$2" && {
                                #printf "${WHITE}UNSETTING socket_dir...${CLEAR}\n"
                                sed -i'.bak' -Ee '/(EMACS_SERVER_SOCKET_DIR)=.*$/ s!!\1=TBD!' "$2"
                        } || { :; }

                } || {
                  [[ "$2" -nt "$1" ]] && { # rc file is newer
                    printf "${YELLOW}rc is newer than system${CLEAR}\n"
                    echo; ls -l $2 $1; echo
                    [[ -w "$1" ]] && { # check if the system file is writable
                      printf "${PURPLE}"
                      cp -ipv "$2" "$1"
                      printf "${CLEAR}"
                    } || {
                      printf "${RED}You must authenticate... ${CLEAR}"
                      printf "${PURPLE}"
                      sudo cp -ipv "$2" "$1"
                      printf "${CLEAR}"
                    }

                    ## update the value of the emacs server-socket-dir in the system file
                    grep -q "EMACS_SERVER_SOCKET_DIR=" "$1" && {
                      socket_dir=$(${EMACS} -Q --batch --eval '(progn (require (quote server))(princ (file-name-as-directory server-socket-dir)))')
                      printf "${WHITE}SETTING socket_dir=${socket_dir}${CLEAR}...\n"
                      sed -i'.bak'-$$ -Ee '/(EMACS_SERVER_SOCKET_DIR)=.*$/ s!!\1='"$socket_dir"'!' "$1"
                    } || { :; }

                    } || {
                      printf "${REDBOLD}ERROR: the files don't match but are the same age?${CLEAR}\n"
                    }
            }
      else
            printf "${CYAN}No difference.${CLEAR}\n"
      fi
      } || {
          tocreate=$( if test -e "$1"; then echo "$2"; else echo "$1"; fi; )
          printf "${WHITE}one file: ${RED}${tocreate} ${WHITE}does not exist...Create?${CLEAR}"
          read -sn 1
          if [[ $REPLY == [yY] ]]
          then
              echo " Creating"
              outof=$( if test -e "$1"; then echo $1; else echo "$2"; fi; )
              mkdir -pv $(dirname "${tocreate}")
              cp -ivp "${outof}" "${tocreate}"
          else
              echo " Not creating"
          fi
      }
  } # end of comp()

  declare -a rcfiles=(/private/etc/profile /private/etc/bashrc /private/etc/tmux.conf ~/.bash_profile ~/.bashrc ~/.tmux.conf)

  ## see usage() abaove
  while getopts "f:t:h" opt
  do
        case $opt in
          'f') from=${OPTARG} ;;
          't') to=${OPTARG}        ;;
          'h') usage 0        ;;
          '?') printf "${RED}ERROR ${CLEAR}\n"; usage 1; ;;
           *) printf "OPTIND: ${RED}${OPTIND}${CLEAR}\n"; usage 1; ;;
        esac
  done

  ## OPTIND must be either 1 (no options) or 5 (2 options)
  if [[ $OPTIND -gt 1 && $OPTIND -ne 5 ]]
  then
        printf "${RED}ERROR: need both -f and -t${CLEAR}\n"
        usage 1
  fi

  ## check for correct combination of from and to
  if [[ -n $from ]]
  then
        if [[ $from == "system" ]]
        then
          if [[ $to != "rc" ]]
          then
              printf "${RED}ERROR: incorrect combination: $from -- $to${CLEAR}\n"
              usage 1
          fi
        elif [[ $from == "rc" ]]
        then
          if [[ $to != "system" ]]
          then
              printf "${RED}ERROR: incorrect combination: $from -- $to${CLEAR}\n"
              usage 1
          fi
        else
          printf "${RED}ERROR; incorrect combination: $from -- $to${CLEAR}\n"
          usage 1
        fi
  fi

  ## everything checks out; now process the files
  for file in "${rcfiles[@]}"
  do
        printf "Considering ${GREEN}$file... ${CLEAR}"

        case $file in
            *etc?profile)   comp $file $TEMPLATES/rc/etc/${COMP}/profile   ;;
            *etc?bashrc)    comp $file $TEMPLATES/rc/etc/${COMP}/bashrc    ;;
            *etc?tmux.conf) comp $file $TEMPLATES/rc/etc/${COMP}/tmux.conf ;;
            *bash_profile)  comp $file $TEMPLATES/rc/${COMP}/bash_profile  ;;
            *bashrc)               comp $file $TEMPLATES/rc/${COMP}/bashrc              ;;
            *tmux?conf)     comp $file $TEMPLATES/rc/${COMP}/tmux.conf     ;;
        esac
  done

Previous: Switch Emacs Init, Up: Build Scripts   [Index]