Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unload hook #129

Open
nyarly opened this issue Jun 20, 2014 · 21 comments

Comments

6 participants
@nyarly
Copy link
Contributor

commented Jun 20, 2014

When leaving an .envrc directory, it'd be nice to be able to run a script to undo changes that happened when entering the dir.

For instance, I'm using chruby for use_ruby - so long as I switch from ruby project to ruby project, it's fine, but leaving direnv dirs, I'm left with "whichever ruby I had last" - being able to chruby 2.0 whenever direnv unloads would be handy.

@nyarly

This comment has been minimized.

Copy link
Contributor Author

commented Jun 20, 2014

I guess I could .envrc a chruby in my homedir, huh?

@zimbatm

This comment has been minimized.

Copy link
Member

commented Jun 20, 2014

How does your use_ruby look like ?

I think that chruby sets environment variables to select the ruby version so direnv should properly revert those changes when going out of the directory. If you're using chruby's auto-switching feature there might be a conflict between direnv and chruby.

@nyarly

This comment has been minimized.

Copy link
Contributor Author

commented Jun 20, 2014

use_ruby(){
  local version=$1
  if [ -z $version ]; then
    version=".ruby-version"
  fi
  if [ -f $version ]; then
    version=$(cat $version)
  fi

  chruby $version
  layout ruby
}

The important part is the chruby - which looks for a matching installed ruby and sets up symlinks for it. I'm specifically not using the chruby/auto.sh script, so my running ruby version doesn't depend on an env var.

Quite reasonably, the answer could be "that's not what direnv is for"...

@zimbatm

This comment has been minimized.

Copy link
Member

commented Jun 21, 2014

Hey nyarly,

I think you also need to source that chruby.sh file at the start of the use_ruby function. direnv starts a bash sub-shell to evaluate the .envrc and the .bashrc is not supposed to be loaded in that context.
According to https://github.com/postmodern/chruby/blob/master/share/chruby/chruby.sh#L32 chruby is also using environment variables so it should be fine.
Alternatively you can also use load_prefix ~/.rubies/$version instead of chruby.

@nyarly

This comment has been minimized.

Copy link
Contributor Author

commented Jun 21, 2014

load_prefix is an interesting idea.

I think I figured out what happened: I used chruby at the commandline to test something in a different ruby and then left the directory. So direnv didn't change back to the original value of e.g. PATH because PATH had been changed while I was in the dir.

@sknop

This comment has been minimized.

Copy link

commented Nov 12, 2014

I have another use case for an unload hook.
I update my shell title when I enter a directory under direnv control:

echo -n -e "\033];In DirEnv\007"

It would be great if I could unset this when I leaving the directory again.

@zimbatm zimbatm added the Feature label Jul 4, 2015

@sknop

This comment has been minimized.

Copy link

commented Sep 29, 2015

Resetting the shell title is exactly the use I am looking for.

@zimbatm

This comment has been minimized.

Copy link
Member

commented Sep 29, 2015

Hey @sknop, I think you can achieve what you want by changing the PS1 no ?

@zimbatm

This comment has been minimized.

Copy link
Member

commented Sep 29, 2015

not tested but something like that:

in_direnv() {
  if [ -n "$DIRENV_DIR" ]; then
    echo -n -e "\033];In DirEnv\007"
  else
    echo -n -e "\033];Out of DirEnv\007"
  fi
}
PS1='$(in_direnv) > '
@sknop

This comment has been minimized.

Copy link

commented Sep 29, 2015

Ah, did not think of using the DIRENV_DIR variable, just discovered that. Not a bad idea, I'll try that.

Thanks

@zimbatm

This comment has been minimized.

Copy link
Member

commented Sep 29, 2015

Just fixed the script, it's working now

@mattford63

This comment has been minimized.

Copy link

commented Sep 14, 2016

I have many dirs each has a code base for a different customer. I can launch the appropriate VPN/sshuttle session on entering the dir. But I can't unload it again :-(

@zimbatm

This comment has been minimized.

Copy link
Member

commented Sep 14, 2016

Hi @mattford63, what would happen if you had two terminals that cd into the same customer folder?

My main issue with implementing the unload hook is that it supposes some sort of system-wide state. The second issue is, what would happen if the terminal is closed? I think this can be fixed but it would be fairly easy to leave the system in an inconsistent state.

@PanisSupraOmnia

This comment has been minimized.

Copy link

commented Jan 5, 2017

I've got a case where this would be useful as well. In order to work on a Rails project that I'm part of, I need to run bundle exec rake sunspot:solr:start: when I enter the folder. However, once I leave that folder I'd like to bundle exec rake sunspot:solr:stop, because I don't need to leave the solr server running in the background taking up resources. Of course I could simply try to remember to stop it when I'm done with it, but that would kind of defeat the whole point of using direnv for this in the first place.

@zimbatm

This comment has been minimized.

Copy link
Member

commented Jan 5, 2017

@nyarly

This comment has been minimized.

Copy link
Contributor Author

commented Aug 10, 2017

I just stumbled into another potential use case for this: I have a directory for presentation slides. In there I've got a script called "presenting.sh" that e.g. xset s noblank (and a bunch of other "don't blank the screen during a presentation" stuff.)

It'd be nice to have that happen automatically and go away when I was done. Related elsewhere is the problem that closing the terminal would mean that those settings wouldn't be reverted, though.

@zimbatm

This comment has been minimized.

Copy link
Member

commented Aug 12, 2017

Interesting, thanks for sharing. In this case I would say that it's the presentation software's responsibility to prevent the screen going to sleep, just like when a video player is in full screen.

@aventurella

This comment has been minimized.

Copy link

commented Feb 18, 2018

Ah, I didn't consider the multiple shells entering the folder problem, aka using something like tmux would present this problem. I often run my unit tests from another shell session/pane and keep my git commands in another. That would definitely be multiple shells, and I see how the issue arises now.

definitely a tricky thing to think about unless state is maintained somewhere.. blah... If the terminal crashes, the state file would effectively be inconsistent.. MORE BLAH!

Tough problem.

What does smartcd do I wonder. They have enter/exit hooks, curious how they handle the same problem or if they even bother and just leave it up to the user to sort out.

@zimbatm

This comment has been minimized.

Copy link
Member

commented Feb 18, 2018

Most use-cases here would be solved with a process manager. direnv doesn't maintain a running process so it would have to be a new project (dirsvc?).

I think the realization is that we have system-level services, per-user services and now we want per-project services. In systemd, per-user services are started when the first user sessions opens and stopped when the last session closes. Similarly we want the per-project services to start when the first shell opens the project, and stop when the last shell leaves it.

Similarly to direnv it would have a shell hook. It would report directory enter and leaves to the daemon, which would then in turn start and stop the services if a specific file is found (.svcrc?).

$ dirsvc status
/home/user/src/project1 (shells: 3, services: 4)
/home/user/src/project2 (shells: 1, services: 1)
$ dirsvc stop /home/user/src/project2 # forcefully close a session if the shell has disappeared
$ cd /home/user/src/project1 # shell hook adds this shell to the session
$ dirctl status # show the running processes for this folder
* mysql: running
* redis: running
$ dirctl logs mysql
...
$ dirctl restart mysql
...

Potentially the hook could also be implemented in tmux which would give a better reporting facility.

The service definition format is unspecified here. It might make sense to adopt something existing like the systemd units.

A last note: the progression between per-system, per-user and per-project is also a concern for build and runtime dependencies. This is already solved by Nix.

@nyarly

This comment has been minimized.

Copy link
Contributor Author

commented Feb 21, 2018

@zimbatm

This comment has been minimized.

Copy link
Member

commented Feb 21, 2018

Yeah makes sense, it would be easier to watch the lifetime of each shell that way. I guess tmux fits that bill already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.