command expansion: how to convince eshell I'm not trying to execute an elisp expression? - emacs

git grep fizzbuzz $(git rev-list --all)
fatal: Invalid object name 'Symbol's function definition is void'.
Of course, the same command in M-x shell works fine.
How do I convince eshell I'm not trying to execute an elisp expression here so I can get the git grep goodness I so clearly seek?

Try:
git grep fizzbuzz ${git rev-list --all}

Works in my emacs if I wrap the $() with backtics, e.g.:
git grep fizzbuzz `$(git rev-list --all)`

Related

How would you write this script, which works perfectly as intended in bash, to work on fish shell?

GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
This works fine in bash, but I can't get it to run in fish shell. Can someone help me figure out what is the equivalent in fish shell? Thanks.
Turns out there is an equivalent script that doesn't need to use $(date)
git commit --amend --reset-author --no-edit
That does the trick. Thanks!
In fish, use the env external command to alter the environment only for the duration of one command. And of course the command substitution syntax and quoting are different:
env GIT_COMMITTER_DATE=(date) git commit --amend --no-edit --date (date)

How to copy Zsh aliases to Eshell

I'm trying to copy using the command provided in here. That is,
alias | sed -E "s/^alias ([^=]+)='(.*)'$/alias \1 \2 \$*/g; s/'\\\''/'/g;" >~/.emacs.d/eshell/alias
This worked with Bash, I was using Emacs-Starter-Kit; but not working with Zsh -- not working means it copied things but to no effect.
[As a side note]
It seems like, I don't have few Eshell default variables i.e. eshell-read-aliases-list, and eshell-aliases-file. So, I even don't know where should my Eshell alias file reside.
Got it working after setting
(setq eshell-directory-name (expand-file-name "./" (expand-file-name "eshell" prelude-personal-dir)))
in post.el (my personal .el file for post-processing) under prelude/personal
... and modified the given bash command to
alias | awk '{print "alias "$0}' | sed -E "s/^alias ([^=]+)='(.*)'$/alias \1 \2 \$*/g; s/'\\\''/'/g;" > ~/.emacs.d/personal/eshell/alias
... and appended that to .zshrc.
Found that alias command, in zsh, prints aliases without prefix alias<space>, unlike bash. Therefore this part
| awk '{print "alias "$0}'

Printing variables and "global symbol $XXX requires explicit package"

I have the following Perl. It attempts to detect a Git Clone (as opposed to an offline zip) and print the repo information. The idea is, if git rev-parse fails, then its probably not a Git repo.
if (system "git rev-parse HEAD") { # Line 234
my $revision = `git rev-parse HEAD | cut 1-16`; # Line 235
my $branch = `git rev-parse --abbrev-ref HEAD`; # Line 236
print "Git repo: $branch ($revision)\n"; # Line 237
} # Line 238
It results in the errors below. If I am parsing What's the differences between system and backticks and pipes in Perl and How can I store the result of a system command in a Perl variable correctly, it should work.
According to How to print variables in Perl, print "Git repo: $branch ($revision)\n" should work. Based on Global symbol requires explicit package, the Q&A says to use # instead of $. I tried to print "Git repo: #branch (#revision)\n", but it resulted in the same errors (with a different symbol).
I have two questions:
Why does Perl think the variable is a package?
What is wrong with the Perl, and how do I fix it?
Global symbol "#branch" requires explicit package name at ./Configure line 237.
Global symbol "#revision" requires explicit package name at ./Configure line 237.
I can't test your script, but this part should be like this:
if(`git rev-parse HEAD 2>&1` !~ /Not a git repository/) {
chomp(my $revision = `git rev-parse HEAD | cut -c1-16`);
chomp(my $branch = `git rev-parse --abbrev-ref HEAD`);
print "Git repo: $branch ($revision)\n";
}

Why doesn't git diff work between two dates?

I checked out a project from an internal GitLab server using Eclipse, then I pulled all the changes. When I view the history from Eclipse. (Team > show in history), it displays the full history of the project.
Now I go to the relevant project from the terminal.
/home/workspace/ProjectX/
I am trying to get the differences between 2 dates with the following command:
git diff --name-only master#{2015-10-10}..master#{2015-11-10} > /home/results/ProjectX/Changes.txt
It wont display any result for that. It displays:
warning: Log for 'master' only goes back to Tue, 10 Nov 2015.
How can I get all the differences in that date range?
In addition to that, how does Eclipse request its history from the remote server. If we can run the same command from the terminal, that should work.
Git parses dates like master#{2015-10-10} using your reflog, which doesn't appear to go back as far as you're searching. But, you can find commits for that date range anyway with rev-list:
git rev-list --since='2015-10-10' --until='2015-11-10' master
You want the files changes between the most recent and the oldest commit in that list, which we can get using head and tail. I'd like to use -n1 and --reverse, but --reverse applies after -n, so we can't.
first=$(git rev-list --since='2015-10-10' --until='2015-11-10' master | tail -1)
last=$(git rev-list --since='2015-10-10' --until='2015-11-10' master | head -1)
git diff --name-only $first..$last
Setting variables and duplicating the rev-list feels clumsy, but the pipe-y version I can come up with is sort of worse. It picks the first and last commits, converts the newline to a space using tr, replaces the new space with .. using sed, then passes the pair off to git diff.
git rev-list --since='2015-10-10' --until='2015-11-10' master | \
(head -n1 && tail -n1) | \
tr '\n' ' ' | \
sed 's/ /../' | \
xargs git diff --name-only

Commit hash of the revision about to be deployed?

I want to add a hook that logs something to the effect of "Hey, I'm about to deploy such-and-such commit." Something like:
before "deploy:update_code" do
logger.info "Deploying #{revision}"
end
Except "revision" in this context seems to yield a ref name (i.e. "master") rather than a commit ID. What construct can I use to get the sha1?
To get the ref, you'll need to shell out to Git:
Here's an example from one of my own projects, where master is fully up-to-date and pushed, and my clean_architecture branch isn't.
~/api git:(clean_architecture) $ git show-ref master
349dabbffec0713ac0fc70cf991dbaff6412ad2b refs/heads/master
349dabbffec0713ac0fc70cf991dbaff6412ad2b refs/remotes/origin/master
~/api git:(clean_architecture) $ git show-ref clean_architecture
14afae560ace128a13336ca01ff2391b678fadaf refs/heads/clean_architecture
bc78906ad0b2814dbc6225b2e14155b66eedffd0 refs/remotes/origin/clean_architecture
Taking that on-board, I'd suggest something like the following to grab the remotely pushed ref hash (as that's the only one the Capistrano 3 can see, Capistrano will do a check like this internally, but you can't access the ref, and will complain if these two values differ, anyway)
First, on the command line:
$ git show-ref clean_architecture | tail -1 | cut -f1 -d ' '
bc78906ad0b2814dbc6225b2e14155b66eedffd0
$ git show-ref clean_architecture | tail -1 | awk '{print $1}'
bc78906ad0b2814dbc6225b2e14155b66eedffd0
(there's about a million ways to do this on linux)
Secondly in Ruby:
$ irb --simple-prompt
>> `git show-ref #{fetch(:branch)}`
=> "349dabbffec0713ac0fc70cf991dbaff6412ad2b refs/heads/master\n349dabbffec0713ac0fc70cf991dbaff6412ad2b refs/remotes/origin/master\n"
Which let's us know we can split this up really easily in Ruby land, and not need cut or awk:
$ irb --simple-prompt
>> `git show-ref #{fetch(:branch)}`.split.first
That should be pretty close, and pretty-portable (where as cut and awk, and splitting that up in the shell with pipes, etc is quite *nix specific and unlikely to work well on Windows)
Drop that in your before task, and you should be set.