Skrypt Bash do wykrywania systemu kontroli wersji poprzez testowanie statusu powrotu komendy

11

Pracuję nad skryptem bash, który chciałbym pracować dla kilku typów VCS. Zastanawiam się nad przetestowaniem, czy katalog jest repozytorium dla systemu, uruchamiając typowe polecenie info i sprawdzając kod powrotu, sukces lub błąd. W pseudokodzie:

if a svn command succeded;
    Then run svn commands
elif a darcs command succeded;
    Then run darcs commands
elif a mercurial command succeded;
    then run hg commands
else 
    something else
fi

Mogę uruchomić polecenie, np. darcs show repoI użyć, $?aby uzyskać jego kod powrotu.

Moje pytanie brzmi: czy istnieje dobry sposób na uruchomienie i zwrócenie numeru kodu powrotu w jednym wierszu? na przykład

if [ 0 -eq `darcs show repo`$? ]; 

Czy muszę zdefiniować funkcję?

Dodatkowym wymaganiem jest wydrukowanie zarówno stderr, jak i stdout.

Niall Murphy
źródło

Odpowiedzi:

15

Jeśli automatycznie sprawdza kod powrotu:

if (darcs show repo); then
  echo "repo exists"
else
  echo "repo does not exist"
fi

Możesz także uruchomić polecenie i użyć && (logiczne AND) lub || (logiczne LUB), aby sprawdzić, czy się udało:

darcs show repo && echo "repo exists"
darcs show repo || echo "repo does not exist"

Przekierowanie stdouti stderrmożna to zrobić razexec

exec 6>&1
exec 7>&2
exec >/dev/null 2>&1

if (darcs show repo); then
  repo="darcs"
elif (test -d .git); then
  repo="git"
fi

# The user won't see this
echo "You can't see my $repo"

exec 1>&6 6>&-
exec 2>&7 7>&-

# The user will see this
echo "You have $repo installed"

Pierwsze dwa execzapisują deskryptory stdini stderrplik, trzecie przekierowuje oba do /dev/null(lub w inne miejsce, jeśli jest to pożądane). Dwa ostatnie execprzywracają deskryptory plików ponownie. Wszystko pomiędzy zostaje przekierowane do nikąd.

Dołącz inne kontrole repo, jak sugerował Gilles.

machać
źródło
Ładne i czyste, jednak te metody drukują wiadomości do użytkownika. Wolałbym, żeby skrypt był cichy (dodałem to do pytania).
Niall Murphy
2
Dlaczego korzystasz z nich w podpowłoce? To jest niepotrzebne.
Chris Down
4

Jak już wspomnieli inni, if commandsprawdza, czy się commandpowiedzie. W rzeczywistości [ … ]jest to zwykłe polecenie, które może być używane poza iflub whilewarunkowo, chociaż jest rzadkie.

Jednak w przypadku tej aplikacji przetestowałbym istnienie charakterystycznych katalogów. Będzie to poprawne w większej liczbie przypadków skrajnych. Wersja Bash / ksh / zsh / dash (niesprawdzona):

vc=
if [ -d .svn ]; then
  vc=svn
elif [ -d CVS ]; then
  vc=cvs
else
  d=$(pwd -P)
  while [ -n "$d" ]; do
    if [ -d "$d/.bzr" ]; then
      vc=bzr
    elif [ -d "$d/_darcs" ]; then
      vc=darcs
    elif [ -d "$d/.git" ]; then
      vc=git
    elif [ -d "$d/.hg" ]; then
      vc=hg
    fi
    if [ -n "$vc" ]; then break; fi
    d=${d%/*}
  done
fi
if [ -z "$vc" ]; then
  echo 1>&2 "This directory does not seem to be under version control."
  exit 2
fi
Gilles „SO- przestań być zły”
źródło
2

Cóż, to nie jest bardzo ładne, ale jest to jeden ze sposobów, aby to zrobić bezpośrednio:

if darcs show repo > /dev/null 2>&1; then <do something>; fi

Z definicji, jeśli testuje się kod wyjścia polecenia, nie trzeba wykonywać jawnego porównania, chyba że chce się czegoś więcej niż sukcesu lub niepowodzenia. Prawdopodobnie jest to bardziej elegancki sposób.

SethG
źródło
0

Inną zwięzłą opcją byłoby:

[ -d .svn ] && { svn command 1; svn command 2; } 
Mihai Rotaru
źródło