Alias no cygwin bash parece não rodar na ordem correta

1

Estou tentando criar um alias para usar no meu shell Cygwin para determinar se o diretório gerenciado pelo Mercurial no qual estou atualmente tem alterações pendentes. O comando "hg st -m" lista todos os arquivos modificados. Infelizmente, não define um valor de saída com base no fato de haver alterações ou não. Então eu tentei capturar a saída e ver se ela não está vazia, canalizando-a através de "wc -l" e verificando se isso é -gt 0, mas parece que tenho um problema maior em que as linhas claramente não estão sendo executadas na ordem espere que eles.

Aqui está o que eu resumi:

alias hgfoo='
pwd
echo L1
localChanges="NOT SET YET"
hasLocal="NOT SET YET"
echo "Before: A${localChanges}Z A${hasLocal}Z"
localChanges='hg st -m'
echo L2
echo "localChanges: A${localChanges}Z"
echo L3
if [ -n "${localChanges}" ] ; then
    echo L3
    hasLocal="YES"
else
    echo L4
    hasLocal="NO"
fi
echo L5
echo "RESULTS: A${hasLocal}Z"
echo L6
'

Eu coloquei as instruções echo "Ln" para depuração. Quando eu executo digitando "hgfoo" em um diretório que possui alterações, vejo a seguinte saída:

/d/hg/succession > hgfoo
/d/hg/succession
L1
Before: ANOT SET YETZ ANOT SET YETZ
L2
localChanges: AL2
localChanges: ANOT SET YETZ
L3
L3
L5
RESULTS: AYESZ
L6
M succession-lib\.actionScriptProperties
M succession-lib\src\main\flex\com\workscape\SuccessionConstants.as
M succession-lib\src\main\flex\com\workscape\succession\nomination\tabmodules\BenchStrengthTab.mxml
M succession-lib\src\main\flex\com\workscape\succession\nomination\tabmodules\BenchStrengthTabMediator.as
M succession-lib\src\main\flex\com\workscape\succession\puremvc\controller\StartupSuccession.asZ
L3
L3
L5
RESULTS: AYESZ
L6

Quando eu o executo em um diretório sem alterações, vejo:

/d/hg/employee-profile > hgfoo
/d/hg/employee-profile
L1
Before: ANOT SET YETZ ANOT SET YETZ
L2
localChanges: AL2
localChanges: ANOT SET YETZ
L3
L3
L5
RESULTS: AYESZ
L6Z
L3
L3
L5
RESULTS: AYESZ
L6

Mesmo esquecendo o fato de que a comparação não está dando certo, em ambos os casos parece estar executando linhas múltiplas vezes e no lugar errado. Isso está me deixando louco.

Alguma pista? Obrigado.

    
por dj_segfault 02.03.2011 / 17:32

2 respostas

4

Este é um bug de longa data na expansão do alias do bash. Eu poderia reproduzi-lo no Debian lenny amd64 com bash 3.2.29 (1), Debian squeeze i386 com 4.1.5 (1), e Windows XP com Cygwin 1.7.7-1 com bash 4.1.9 (3).

Alguns experimentos mostram que o bug é muito sensível a variações em como o alias é usado. hgfoo ou hgfoo : exibe o erro, mas { hgfoo :; } e (hgfoo) funcionam bem. Usar uma função em vez de um alias também funciona.

Eu investiguei um pouco, tentando extrair um exemplo menor. A estranheza parece resultar de ter uma nova linha no pseudônimo. Aqui está um exemplo simples em que o bash (3.2.29 ou 4.1.9) se comporta mal. Este alias funciona como esperado (da minha leitura do Single Unix v3) sob pdksh, ksh93, ash e zsh no Debian lenny, a saber oops prints foo bar .

$ alias oops='a=$(echo bar)
> echo foo $a'
$ oops
foo foo echo bar

O bug pode estar relacionado a um bug reportado sobre" aliases atrasados estranhos ", mas essa discussão se concentra em continuações de linha (barra invertida-nova linha) que não é usada aqui.

Em qualquer caso, use uma função! Aliases são para one-liners onde você está apenas especificando algumas opções padrão para um comando. Uma função teria o benefício adicional de poder transmitir argumentos para hg :

hgfoo () {
  localChanges=$(hg st -m "$@")
  …
}

Inicialmente pensei que isso fosse um bug do Cygwin, mas como o ak2 apontou, este bug também ocorre no Linux.

    
por 03.03.2011 / 21:06
0

Eu tenho que trabalhar. Foi de fato os backticks causando os problemas. Eu refatorei isso como

hg st -m | grep -q M

em seguida, verificou o valor de saída do grep, que está funcionando perfeitamente.

    
por 03.03.2011 / 15:35

Tags