Unable to svn diff using meld - linux

I want to use meld to view the difference between revisions. I installed meld and then executed in the project directory:
svn diff -r 2165:2182 --diff-cmd meld
but it thows up the following error:
Index: app/models/college_friends_count.rb
===================================================================
svn: E200012: Process 'meld' failed (exitwhy 2)
Can anybody tell me what is going wrong here?

I believe E200012 means the underlying process (meld) exited with a non-zero exit code. Lots of diff tools do this to indicate the result of the diff operation (0 = no difference 1 = differences, etc).
Though my version of meld doesn't appear to use non-zero exit codes, I know colordiff does, which halts SVN during a directory-crawling "svn diff", like in your example above. Try it on a file that doesn't have any changes to test.
A good fix is to to make your own diff command, let's say you call it meld_svn:
#!/bin/bash
meld "$6" "$7"
exit 0
So what we're doing is ignoring meld's exit codes, and exiting with our own (which won't stop SVN). The quotes around the arguments mean that filenames with spaces in them won't break your script.
Make it executable, then edit your ~/.subversion/config and set the diff-cmd to "meld_svn". This works great for colordiff, should fix your problem with meld if meld's indeed exiting with non-zero exit codes.
I hope that helps.

For me the problem was that by default svn passes -u as an option to the external diff command, and meld doesn't expect or that flag.
The -x flag for svn-diff allows you to to override this default flag:
svn diff -x \"\" --diff-cmd meld
This replaces -u with "" on melds command line, the escapes are required so that your shell doesn't parse the quote-marks the first time round and instead passes them to SVN, who passes it onto the meld command line.
(btw, using echo as the diff-cmd allows you to easily inspect what SVN would send to meld)

Related

How to parse but not execute it? [duplicate]

Is it possible to check a bash script syntax without executing it?
Using Perl, I can run perl -c 'script name'. Is there any equivalent command for bash scripts?
bash -n scriptname
Perhaps an obvious caveat: this validates syntax but won't check if your bash script tries to execute a command that isn't in your path, like ech hello instead of echo hello.
Time changes everything. Here is a web site which provide online syntax checking for shell script.
I found it is very powerful detecting common errors.
About ShellCheck
ShellCheck is a static analysis and linting tool for sh/bash scripts. It's mainly focused on handling typical beginner and intermediate level syntax errors and pitfalls where the shell just gives a cryptic error message or strange behavior, but it also reports on a few more advanced issues where corner cases can cause delayed failures.
Haskell source code is available on GitHub!
I also enable the 'u' option on every bash script I write in order to do some extra checking:
set -u
This will report the usage of uninitialized variables, like in the following script 'check_init.sh'
#!/bin/sh
set -u
message=hello
echo $mesage
Running the script :
$ check_init.sh
Will report the following :
./check_init.sh[4]: mesage: Parameter not set.
Very useful to catch typos
sh -n script-name
Run this. If there are any syntax errors in the script, then it returns the same error message.
If there are no errors, then it comes out without giving any message. You can check immediately by using echo $?, which will return 0 confirming successful without any mistake.
It worked for me well. I ran on Linux OS, Bash Shell.
I actually check all bash scripts in current dir for syntax errors WITHOUT running them using find tool:
Example:
find . -name '*.sh' -print0 | xargs -0 -P"$(nproc)" -I{} bash -n "{}"
If you want to use it for a single file, just edit the wildcard with the name of the file.
null command [colon] also useful when debugging to see variable's value
set -x
for i in {1..10}; do
let i=i+1
: i=$i
done
set -
For only validating syntax:
shellcheck [programPath]
For running the program only if syntax passes, so debugging both syntax and execution:
shellproof [programPath]
Bash shell scripts will run a syntax check if you enable syntax checking with
set -o noexec
if you want to turn off syntax checking
set +o noexec
There is BashSupport plugin for IntelliJ IDEA which checks the syntax.
If you need in a variable the validity of all the files in a directory (git pre-commit hook, build lint script), you can catch the stderr output of the "sh -n" or "bash -n" commands (see other answers) in a variable, and have a "if/else" based on that
bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \; 2>&1 > /dev/null)
if [ "$bashErrLines" != "" ]; then
# at least one sh file in the bin dir has a syntax error
echo $bashErrLines;
exit;
fi
Change "sh" with "bash" depending on your needs

Suppress echo of command invocation in makefile?

I wrote a program for an assignment which is supposed to print its output to stdout. The assignment spec requires the creation of a Makefile which when invoked as make run > outputFile should run the program and write the output to a file, which has a SHA1 fingerprint identical to the one given in the spec.
My problem is that my makefile:
...
run:
java myprogram
also prints the command which runs my program (e.g. java myprogram) to the output file, so that my file includes this extra line causing the fingerprint to be wrong.
Is there any way to execute a command without the command invocation echoing to the command line?
Add # to the beginning of command to tell gmake not to print the command being executed. Like this:
run:
#java myprogram
As Oli suggested, this is a feature of Make and not of Bash.
On the other hand, Bash will never echo commands being executed unless you tell it to do so explicitly (i.e. with -x option).
Even simpler, use make -s (silent mode)!
You can also use .SILENT
.SILENT: run
hi:
echo "Hola!"
run:
java myprogram
In this case, make hi will output command, but make run will not output.
The effect of preceding the command with an # can be extended to a section by extending the command using a trailing backslash on the line. If a .PHONY command is desired to suppress output one can begin the section with:
#printf "..."

Discovering the cause of Vim exit status

On running:
vim /tmp/blah
:q
echo $?
I get an exit status of 1. This is breaking various things including Git. If I run vim without my vimrc:
vim -u NONE /tmp/blah
:q
echo $?
I get an exit status of 0. I use Pathogen so this also effectively disables plugins. Does anyone have a suggestion for efficiently determining the cause of the exit status? I'm aware of running Vim verbosely and logging to a file. Should I be looking for something specific in this file?
If there is a method of finding the exact line that determines the exit status I would love to know of it as searching around didn't turn much up.
Finally found this command in help: :cq[uit]. So after you do verbose logging, search for \<cq\%[uit]\>.
Update: There are also methods to alter the exit status using vim compiled with some interpreters support: at least, the following works:
python import sys
python sys.exit(1)
" (same for python3)
perl exit 1
I do not know other languages enough to write here examples of code that would quit vim with different exit status. Note also that such commands inside files sourced using :pyfile, :rubyfile and other :*file should also work, as well as this code in a modules not distributed with plugin.
I think the most efficient way here at this point is disabling plugins until you find the source of the problem.

Bash: call script with customized keyboard shortcuts?

Lets say I have a script, "myscript.sh", with contents being simply echo $PWD. I'd like to bind somehow this script to a key combo in bash (gnome-terminal) - so that when I press this key combination, the output of "myscript.sh" is inserted ("pasted") at the cursor position in the terminal.
Apparently, bash history and line manipulation is handled by readline - and the references I got for bash keyboard shortcuts, do reference readline:
bash keyboard shortcuts
Bash Reference Manual: Bindable Readline Commands
I've also seen in Bash Reference Manual: Readline Init File Syntax that the key bindings for bash can be listed by using bind -p (see help bind [not 'man bind'] for more). So maybe this question would better be titled as "_binding macros to custom keyboard shortcuts in readline" :) But in any case, is what I want possible to do?
I guess an alternative would be to have the script be something like "pwd | xsel -b", and then I call it on terminal - and I can paste afterwards; but I'd still like a single keyboard shortcut instead, say like Ctrl-Alt-H (which seems to be not used for anything), which will immediately insert/paste script output when pressed.
Thanks in advance,
Cheers!
EDIT: Just to clarify - here is my use case where I'd like this facility. I'm usually cd'd in a project folder, usually named something like myproject-folder-0012a, which is under revision control by svn. And there is a bunch of these folders. So quite often, I do commits where the first word of the message is the directory name, as in:
svn ci -m "myproject-folder-0012a: here a commit message"
But that is what I don't like - first I type 11 characters, which go rather fast:
svn ci -m "
And then, I cannot use autocompletion to get the name (i'm inside the folder) - which means I either have to fully type it (no way :)), or I copy paste it from the prompt (which requires selection - press mouse, drag, release mouse; then Ctrl+Shift+C, and then Ctrl+Shift+V, plus any left/right keys if I miss allignment - plus deletions and such if I make the copy wrong).
Meaning - so much work, just to get the bloody folder name for a bloody commit message :( I'd MUCH rather press something like (say) Ctrl-Alt-H, and have the folder name automatically inserted at cursor position, and be done with it :)
My suggestion for xsel is only because I could put it into a "global" script - say symlink it as /usr/bin/myscript (and obviously, the contents of the script are echo $(basename $PWD) rather than just pwd for my needs), and then I could do:
$ myscript # this puts directory name in clipboard
$ svn ci -m "[CTRL+SHIFT+V TO PASTE HERE]myproject-folder-0012a[NOW TYPE]: here a commit message"
... which sort of makes the workload less, but still - then I have to remember what the script name is, and call it, before I type the svn command (and I don't always remember that)... And still - I have to call a command, and then press a key combo; why shouldn't I just press a key combo once, and be done with it ??! :)
Well, hope this clarifies my problem a bit better ....
EDIT2: However, another reason why a bash keyboard shortcut would be useful, is that then I could also "paste/insert current directory name" not only in shell commands - but also in terminal programs, say like nano (where it would, arguably, be more difficult to use bash script or function expansion directly).
Simple version:
This command at a shell prompt:
bind '"\ee": "${PWD##*/}\e\C-e"'
or this line added to your ~/.inputrc:
"\ee": "${PWD##*/}\e\C-e"
will cause Alt-e to insert the basename of the current directory on the command line. It requires that the default binding of the readline function shell-expand-line which is \e\C-e be present (this could be adapted if it's different). I'm also making the assumption that you're using Bash's emacs mode.
Unfortunately, it causes things that have already been typed to be expanded as well. One of the affects of this is that after having typed:
svn ci -m "
and pressing Alt-e, the quotation mark will have disappeared. There are a couple of ways to deal with this.
One, assume that all you'll lose is the quote and either manually add it back or have the readline macro add it for you:
bind '"\ee": "${PWD##*/}\e\C-e\eb\"\C-e"'
which just isn't very satisfactory.
Advanced version:
Or, two, kill the line, do the insertion, then yank the line back:
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b"'
or
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ef\C-f"'
This leaves the rest of the line intact (nothing else is expanded or deleted), but it uses the kill ring, so it may leave it in a state that's different than you expect (if you're using it). It also inserts a space after the inserted directory name (the spaces in the macro are used to ensure that older kill-ring contents are not regurgitated if the macro is executed at the beginning or end of the line). The macro should work regardless of the position of the cursor in the line. The insertion will be made at the cursor's position, leaving the cursor in the same position [in the first version].
Edit: The second version leaves the cursor after the dirname and space that are inserted.
Edit 2:
The readline function shell-forward-word (unbound) does a better job than forward-word (\ef) for this. You can make use of that like this:
bind '"\ew":shell-forward-word'
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ew\C-f"'
By the way, you should know that Bash keyboard shortcuts are not active in other programs such as nano.
Ok, not really an answer, but I'd just like to summarize the comments I got so far, which are useful for my problem. However, the question as it stands - in respect to bash keyboard shortcuts running arbitrary scripts - is still not answered (I'd still prefer doing all this with a single key combo :))
First, I can use a 'global' script like:
$ sudo bash -c 'cat > /usr/bin/bpwd <<EOF
#!/bin/bash
basepwd=\$(basename \$(pwd))
echo -n \$basepwd # suppress line ending
# exec 1>/dev/null # debug: redir stdout to null
echo -n \$basepwd | xsel -i -b # suppress LF, and make xsel read from stdin
# exec 1>/dev/tty # debug: restore stdout
EOF
chmod +x /usr/bin/bpwd'
Or, I can add bash functions to my .bashrc (note: make sure you reload bash after you add these lines to .bashrc - for example, simply by typing bash in your current terminal):
$ echo '
bpwd2() { basepwd=${PWD##*/} ; echo -n $basepwd | xsel -i -b ; echo -n $basepwd ; }
svnci-test() { echo -n "$(bpwd2): $*" ; }
svnci-m() { svn ci -m "$(bpwd2): $*" ; }' >> ~/.bashrc
Basically, I misunderstood Reese Moore's suggestion originally - you can indeed use backticks - consider this command session (after the above commands have been ran):
$ bpwd
Desktop\
$ bpwd2
Desktop\
$ echo `bpwd`
Desktop
$ echo "`bpwd2` 2"
Desktop 2
This is what I needed to understand Moore's "the output from the backticked commands will be used as input on the executed command" (however, one also needs to take care to clean the line endings from the output); or, in my case, I can call
svn ci -m "`bpwd`: my message here"
# svn ci -m "${PWD##*/}: my message here" # alternatively
... or, I could follow camh's suggestion, and use svnci-m as a function (in my case, I almost never use additional arguments to svn ci, and so my version is slightly different). And to test whether arguments are passed correctly, I can use the svnci-test function:
$ svnci-test "my message"
Desktop: my message\
Thanks for the comments so far,
Cheers!
One way to do what you want with a single key press is to take advantage of programmable completion in bash. You possibly have some programmable completion set up with the bash_completion tool/package. If not, look into that to see the specifics of how it is done.
The idea is to have the programmable completion recognise when you have hit at the start of a svn commit message and then have it return a single completion which is the text you want to insert (the basename of the current directory).
I've only dabbled with programmable completion so I can't give you the details, but the above-mentioned bash_completion package or the subversion completion script may be a good start.

How do I syntax check a Bash script without running it?

Is it possible to check a bash script syntax without executing it?
Using Perl, I can run perl -c 'script name'. Is there any equivalent command for bash scripts?
bash -n scriptname
Perhaps an obvious caveat: this validates syntax but won't check if your bash script tries to execute a command that isn't in your path, like ech hello instead of echo hello.
Time changes everything. Here is a web site which provide online syntax checking for shell script.
I found it is very powerful detecting common errors.
About ShellCheck
ShellCheck is a static analysis and linting tool for sh/bash scripts. It's mainly focused on handling typical beginner and intermediate level syntax errors and pitfalls where the shell just gives a cryptic error message or strange behavior, but it also reports on a few more advanced issues where corner cases can cause delayed failures.
Haskell source code is available on GitHub!
I also enable the 'u' option on every bash script I write in order to do some extra checking:
set -u
This will report the usage of uninitialized variables, like in the following script 'check_init.sh'
#!/bin/sh
set -u
message=hello
echo $mesage
Running the script :
$ check_init.sh
Will report the following :
./check_init.sh[4]: mesage: Parameter not set.
Very useful to catch typos
sh -n script-name
Run this. If there are any syntax errors in the script, then it returns the same error message.
If there are no errors, then it comes out without giving any message. You can check immediately by using echo $?, which will return 0 confirming successful without any mistake.
It worked for me well. I ran on Linux OS, Bash Shell.
I actually check all bash scripts in current dir for syntax errors WITHOUT running them using find tool:
Example:
find . -name '*.sh' -print0 | xargs -0 -P"$(nproc)" -I{} bash -n "{}"
If you want to use it for a single file, just edit the wildcard with the name of the file.
null command [colon] also useful when debugging to see variable's value
set -x
for i in {1..10}; do
let i=i+1
: i=$i
done
set -
For only validating syntax:
shellcheck [programPath]
For running the program only if syntax passes, so debugging both syntax and execution:
shellproof [programPath]
Bash shell scripts will run a syntax check if you enable syntax checking with
set -o noexec
if you want to turn off syntax checking
set +o noexec
There is BashSupport plugin for IntelliJ IDEA which checks the syntax.
If you need in a variable the validity of all the files in a directory (git pre-commit hook, build lint script), you can catch the stderr output of the "sh -n" or "bash -n" commands (see other answers) in a variable, and have a "if/else" based on that
bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \; 2>&1 > /dev/null)
if [ "$bashErrLines" != "" ]; then
# at least one sh file in the bin dir has a syntax error
echo $bashErrLines;
exit;
fi
Change "sh" with "bash" depending on your needs

Resources