You are not logged in.

#1 2017-06-02 10:49:52

lilac-dust
Member
Registered: 2017-05-25
Posts: 2

[SOLVED] Alias just inside directory

Is there a way to make an alias in a shell that works only within a certain directory?
I'm using zsh and I want to alias git commands ('add' to 'git add', 'commit' to 'git commit', etc.), but only when in a git directory. Is this possible? Has anyone done it before?

p.s.: I do realise commands like rm will be messed up, but I'm fine typing \rm when I need an actual rm inside a git directory. That's actually the precise reason I want the alias to only work inside git directories.

Thanks for your time.

Last edited by lilac-dust (2017-06-06 05:06:49)

Offline

#2 2017-06-02 11:59:10

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,546
Website

Re: [SOLVED] Alias just inside directory

It sounds like an odd goal to me, but you could use a conditional in a function (but not an alias):

function rm() { [[ -d .git ]] && git rm $@ || /usr/bin/rm $@; }

You could also use a PROMPT_COMMAND or similar, to check the current working directory and set/unset aliases.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3 2017-06-02 12:16:26

jab2870
Member
Registered: 2017-03-20
Posts: 20

Re: [SOLVED] Alias just inside directory

You might be interested in Smart CD

You would have to set it up for each git directory but it allows you to run commands on entering / leaving a directory.

It also has a very helpful command for aliases.  It will set up the alias when you enter and remove it when you leave.

Offline

#4 2017-06-02 12:23:34

Ropid
Member
Registered: 2015-03-09
Posts: 1,069

Re: [SOLVED] Alias just inside directory

Trilby wrote:

It sounds like an odd goal to me, but you could use a conditional in a function (but not an alias):

function rm() { [[ -d .git ]] && git rm $@ || /usr/bin/rm $@; }

You could also use a PROMPT_COMMAND or similar, to check the current working directory and set/unset aliases.

Using && || will execute "/usr/bin/rm $@" if the "git rm $@" command returns an error exit status. It's better to be more wordy and use the normal "if-then-else" structure so that nothing unexpected can happen:

rm() {
    if [[ -d .git ]]; then
        git rm "$@"
    else
        /usr/bin/rm "$@"
    fi
}

Here's what I mean about && and || instead of if-then-else:

First, this here works like expected:

$ true && echo then || echo else
then

$ false && echo then || echo else
else

But here's how it behaves if the "then" part returns an error, where it executes the "else" part as well:

$ true && { echo then; false; } || echo else
then
else

Offline

#5 2017-06-02 12:53:09

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,546
Website

Re: [SOLVED] Alias just inside directory

Ropid, that was intentional.  Really, I was thinking about getting rid of the initial conditional and redirecting error output of the git command.b  If the git command fails, one would want the "normal" command.  The logic is "use git rm if possible, otherwise use regular rm".


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#6 2017-06-02 14:33:36

Xyne
Forum Fellow
Registered: 2008-08-03
Posts: 6,965
Website

Re: [SOLVED] Alias just inside directory

edit 2
Here's the improved solution using the suggestion from below. It's so obvious now that I feel stupid, but in my defense I was focused on the "[[ -d .git ]]" idea above tongue
Bikeshedding is fun smile

function rm()
{
  if [[ $(git rev-parse --is-inside-work-tree 2>/dev/null) = true ]]
  then
    echo git rm "$@"
  else
    echo /usr/bin/rm "$@"
  fi
}

/edit 2

The .git directory may be in a parent directory. This will check further up the directory path hierarchy.

#!/bin/bash

function is_git()
{
  local dpath_="$PWD/"
  [[ $dpath_ == // ]] && dpath_=/
  while [[ $dpath_ != // ]]
  do
    if [[ -d $dpath_.git ]]
    then
      return 0
    fi
    dpath_="${dpath_%/*/}/"
  done
  return 1
}

if is_git
then
  git rm "$@"
else
  /usr/bin/rm "$@"
fi

edit 1
As a single "rm" function:

function rm()
{
  local dpath_="$PWD/"
  local is_git_=false
  [[ $dpath_ == // ]] && dpath_=/
  while [[ $dpath_ != // ]]
  do
    if [[ -d $dpath_.git ]]
    then
      is_git_=true
      break
    fi
    dpath_="${dpath_%/*/}/"
  done
  if $is_git_
  then
    echo git rm "$@"
  else
    echo /usr/bin/rm "$@"
  fi
}

Last edited by Xyne (2017-06-05 10:57:05)


My Arch Linux Stuff • Forum Etiquette • Community Ethos - Arch is not for everyone

Offline

#7 2017-06-02 14:50:59

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,546
Website

Re: [SOLVED] Alias just inside directory

or just

function is_git() { git branch >/dev/null 2>&1; }

"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#8 2017-06-02 16:07:07

eschwartz
Fellow
Registered: 2014-08-08
Posts: 4,097

Re: [SOLVED] Alias just inside directory

I'd suggest using

[[ $(git rev-parse --is-inside-work-tree 2>/dev/null) = true ]]

actually, since unlike branch, rev-parse is a low-level command meant to be useful -- and used -- for scripting. Specifically, this lets you tell the difference between being in a bare git repo, or the .git directory of a git repo, and actually being in what you meant to ask about.

rev-parse lets you learn all kinds of useful things; it is also what the official bash-completion script for git uses for things like this, see the __git_find_repo_path function.


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#9 2017-06-06 05:06:26

lilac-dust
Member
Registered: 2017-05-25
Posts: 2

Re: [SOLVED] Alias just inside directory

Thanks everyone
I'll try Xyne's edited solution for now and report back in case anything goes wrong, but for now this seems solved.
Also Smart CD sounds really interesting, but it might take a while before I look into it.
Once again, thank you for the ideas!

Offline

Board footer

Powered by FluxBB