mostra o status limitado do git diff em ls, somente nos diretórios git

1

Isso pode ser um problema estranho, mas eu gostaria de substituir o comportamento de ls quando em um diretório git.

Eu quero extrair algumas estatísticas de diferenças do último commit e anexá-las ao final do ls . Quando no root do projeto git, eu quero fazer um prompt específico como este:

app/
test/
.gitignore
test.py
run.py
README.md

+ 11 lines
- 3 lines
Last commit: "add a new test for deployment" (Oct 14, 2014)

Quando mais profundo do que a raiz, quero criar um prompt como este (digamos, eu cd'd para test/ e, em seguida, use o comando ls ):

test/
├── __init__.py
├── test_deploy.py
└── test_add_user.py (+3 lines since last commit)

Pontos de bônus: verde / vermelho colorido para linhas de mais / menos e ótimas guias uniformes sobre informações de git.

Como isso pode ser alcançado?

    
por corvid 10.11.2014 / 21:06

1 resposta

1

Primeiro, para criar um ls personalizado, a maneira mais fácil é proceder da seguinte forma:

  1. Crie um diretório $HOME/bin
  2. Adicione $HOME/bin ao seu PATH . Para fazer isso, abra o arquivo ~/.bashrc em seu editor de texto favorito e adicione a seguinte linha ao final:

    export PATH=$HOME/bin:$PATH
    

    Note que é importante que você prefixe $HOME/bin ao seu PATH , para que os executáveis nele tenham precedência sobre outros executáveis com o mesmo nome ao longo do seu PATH (como , no seu caso, o comando ls )

  3. Crie um arquivo $HOME/bin/ls com o conteúdo que vou postar abaixo.
  4. Torne-o executável: chmod 755 $HOME/bin/ls .
  5. Você provavelmente precisará reiniciar seu terminal.

Em segundo lugar, seu novo $HOME/bin/ls deve se comportar da seguinte maneira: ele verifica se o diretório atual é um repositório git e

  • se não, simplesmente delega ao executável normal /bin/ls .
  • se sim, ele cria a saída solicitada, dependendo se a pasta atual é a raiz do repositório git ou se é mais profunda.

Eu rapidamente copiei esse script para você. Não é de modo algum perfeito, mas deve ser bem próximo do que você quer, e você pode trabalhar facilmente a partir daí. : -)

#!/bin/bash

# determine if we're in a git repo, what the root dir is, and assign it to GIT_ROOT, all in one swoop
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)

# if not in git repo, relay to normal ls
if (( $? )); then
  /bin/ls "$@"

# if in git repo, are we in root dir?
elif [ "x$GIT_ROOT" = "x$PWD" ]; then
  # first, normal ls with 1 file per line, also pass along other parameters
  /bin/ls -1 "$@"
  echo
  # a few git stats
  GIT_DIFF=$(git diff --stat | tail -1)
  # any insertions?
  echo $GIT_DIFF | grep insertion >/dev/null
  if (( ! $? )); then
    # bonus points: color in green
    echo -e "\e[0;32m+ $(echo $GIT_DIFF | sed 's/.*, \([[:digit:]]\+\) insertion.*//;') lines\e[0m"
  fi
  # any deletions?
  echo $GIT_DIFF | grep deletion >/dev/null
  if (( ! $? )); then
    # bonus points: color in red
    echo -e "\e[0;31m- $(echo $GIT_DIFF | sed 's/.*, \([[:digit:]]\+\) deletion.*//;') lines\e[0m"
  fi
  # Finally, display last commit message and date
  git log -1 --pretty='Last commit: "%s" (%ad)'

# otherwise, we're depper in a git repo
else
  echo -e "\e[1;34m${PWD##*/}\e[0m"
  IFS=$'\n'
  for file in $(tree -C | tail -n +2 | head -n -2); do
    filename=$(echo $file | cut -d" " -f 2-)
    echo -n $file
    # a few git stats
    GIT_DIFF=$(git diff --stat "$(echo $filename | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")")
    # any insertions?
    echo $GIT_DIFF | grep insertion >/dev/null
    if (( ! $? )); then
      # bonus points: color in green
      echo -ne " \e[0;32m(+ $(echo $GIT_DIFF | sed 's/.*, \([[:digit:]]\+\) insertion.*//;') lines since last commit)\e[0m"
    fi
    # any deletions?
    echo $GIT_DIFF | grep deletion >/dev/null
    if (( ! $? )); then
      # bonus points: color in red
      echo -ne " \e[0;31m(- $(echo $GIT_DIFF | sed 's/.*, \([[:digit:]]\+\) deletion.*//;') lines since last commit)\e[0m"
    fi
    echo
  done

fi

Demo

Nota: a saída é bem colorida, embora claramente isso não apareça aqui.

$ ls
app
README.md
run.py
test
test.py

+ 11 lines
- 3 lines
Last commit: "add a new test for deployment" (Fri Nov 21 04:20:37 2014 +0100)
$ cd test/
$ ls
test
├── bla
├── __init__.py
├── test_add_user.py (+ 3 lines since last commit)
└── test_deploy.py
    
por Malte Skoruppa 21.11.2014 / 04:31