I have a few git svn related functions that see if I have to pull/push from/to the repository.

My problem is that the functions I've written to gather this information are too slow. I'd like to make them async so that PS1 shows a default, if though the data produced by the functions is ready I want it printed.

I'd like to have these information in my prompt – so that, for example, I know if I have to pull – without doing a git svn fetch everytime.

This is the function I call to add a ↑ to my PS1 if I have to push my changes.

function hasToPush {
    (($1 == 0)) && 
        (git svn dcommit --dry-run 2>/dev/null | grep -q "diff-tree" && echo "↑")

These are the functions I call to add a ↓ if I have to pull. The first is used to refresh my index every 2 minutes so that I can do the (($latest > $current)) check.

function loopingGitSvnFetch {
     sleep 120
     git svn fetch &>/dev/null
loopingGitSvnFetch &
function hasToPull {
    (($1 == 0)) && (
        latest=$(git svn log | awk 'NR==2' | cut -d ' ' -f1 | tr -d 'r')
        (($latest > $current)) && echo "↓"

To make them async, I've tried to put them together like this:

function async {
     git diff-index --quiet --cached HEAD &>/dev/null
     dirty=$(echo $?)
     push=$(hasToPush $dirty)
     gitsvn=$(git svn info 2> /dev/null | grep Revision)
     gitsvn=${gitsvn#Revision: }
     pull=$(hastoPull $dirty $gitsvn)
     callback $push $pull
     } &

But that produces the same slow behaviour. I've tried to put results in a file and then read it after, but I don't like that approach.

I've thought about using PROMPT_COMMAND. But that would not be async; it would be on demand.

Could you shed some light on how PS1 behaves or on what I'm doing wrong? Thank you in advance.

PS: Could someone with 300 rep add the async and ps1 tags?


I added these line to my .bashrc as a simple test, it seemed to work, so having rewrote them (I reverted my previous attempt) seems was a good thing :)

while true;
    discoverScmInfo &>~/.ps1
    sleep 1
done &
PS1='$(customW)$(cat ~/.ps1)\$ '

I'll put this in a function and check if the job is already running before calling it. Sorry about this, after all it seems that all I needed was to write about it. :)

  • Regarding tags: async might be useful, but one might usually have either jobs or parallel instead, so we'll see if it catches on. But defnitely not PS1 - it is just a shell configuration variable; you have the prompt tag for what you mean. Nov 23, 2011 at 17:46
  • 1
    Why don't you like the file-based approach? It really seems the only reasonable one to me. Maybe optimizing it would be enough for you - please show, how did you use this approach. Nov 23, 2011 at 17:51
  • While I was coding I thought it would not be such a great idea to start creating dotfiles around my home. I reverted all my changes to bashrc, so now I've reimplemented it and it seems to work ok ^^". Sorry about this. Btw, since this is not a problem anymore, do you have some hints on making this better? Nov 23, 2011 at 18:06

1 Answer 1


re: your solution of a loop every second: you could write to a file in /tmp, instead of in your home directory. And PS1=$(customW)$(< ~/.ps1)\$ ' would save a fork/exec of cat.

re: the original question: how to get an async update to PS1: To start an async write to PS1:

  • set PROMPT_COMMAND to a function that checks if the data is available.
    • If it is, update PS1 and unset PROMPT_COMMAND
    • If not, leave PS1 with the old or placeholder value.

Use a file in /tmp for the async IO to write to, and PROMPT_COMMAND to read from.

I think this should work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.