4

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')
        current=$2
        (($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?

EDIT:

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;
do
    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. :)

Sildoreth
  • 1,822
  • 8
  • 23
  • 40
  • 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. – rozcietrzewiacz Nov 23 '11 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. – rozcietrzewiacz Nov 23 '11 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? – Alberto Zaccagni Nov 23 '11 at 18:06

1 Answers1

2

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.

Peter Cordes
  • 6,328
  • 22
  • 41